Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**********************************************************************************
- * @file FlashProgramming.pde For Maple STM32F1XX Medium 128 KB Flash
- * @author Samtal
- * @version V1.2.0
- * @date 25-SEP-2011 (added runtime page entry)
- * @brief Basic flash read / write / erase functions for Maple, Main program body
- *********************************************************************************
- * PLESE READ THESE INSTRUECTIONS
- * WARNING: Writing and erasing flash may cause unpredicted results, including
- * destruction of the boot section and the programs.
- * Make sure you know what you do before start.
- * This sample program enables erasing and writing of pages 120-127 only, but DO NOT
- * rely on the program protection. Remember: Nothing (and no one) is perfect !!
- * The functions used were missing in the original libMaple .h and .c files and are
- * added here as direct registry commands.
- * Communication here is by Serial1 port. If you use USB only, rename all Serial1 to SerialUSB.
- *********************************************************************************/
- #include "stdlib.h" //Included explicitly for proper data printing.
- //#include "dma.h"
- #include "flash.h"
- //#include "flash.c" //Only contains 2 function (latency and prefetch) that are implemented here
- //Setting the user's demo parameters:
- uint16 demo_data[1024]; //Build the demo array in the setup()
- uint16 demo_cells=100; //Set up the number of demo cells you wish to use for read and write.
- byte page=125; // Set the flash page to use.
- byte input;
- uint16 flash_data[1024];
- int flash_base=0x08000000; //= 134217728;
- int lower_address_limit = 0x801E000 ; //Lower safety page limit for the demo Page 120
- int upper_address_limit = 0x0801FFFF ; //Flash upper address. The upper page (127) limit
- int data_address[1024]; // The address array. Used for information only.
- byte* read_address;
- uint16* write_address;
- /*****************************************************************************/
- void setup()
- /*****************************************************************************/
- {
- Serial1.begin(56000); //Optional, if Serial1 is used.
- /* Building demo data array.
- * Here we build an array starting at 65535, going down by one for each memory location.
- * User may use any other function to build the array.
- */
- for (uint16 d=0;d<demo_cells;d++)
- {
- demo_data[d]=0xFFFF-d;
- // Serial1.println(demo_data[d],BIN); //Optional, for testing
- }
- FLASH_BASE->ACR |= 1<<4; //ACR bit 4, Prefetch enable.
- FLASH_BASE->ACR |= 1<<1; //ACR bit 1, Set latency 010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz
- startup_message();
- } //End Setup
- /*****************************************************************************/
- void startup_message() //Can be repeated by sending 't'
- /*****************************************************************************/
- {
- Serial1.println();
- Serial1.println("Welcome to the Flash Read / Write / Erase Demo by samtal");
- Serial1.println("This program demonstrates the use of the Maple r5 flash programming");
- Serial1.println("Due to the lack of built libMaple functions, This program acts directly on registers");
- Serial1.println("Here are some basic instructions:");
- Serial1.println("1. For safety, the demo is limited to flash pages 120-127 that are normally free,");
- Serial1.println(" but in some occasions may interfere with program.");
- Serial1.println("2. A demo array is built in the setup and used. You may build any other array");
- Serial1.println("3. Each Write or Erase command is automatically followed by flash lock.");
- Serial1.println(" You must unlock (u) the flash prior to Write or Erase command.");
- Serial1.println("4. The start page, offset from start and number of flash cells to use are user defined");
- Serial1.println(" in setup. You may alter the numbers, but do not exceed the flash limits.");
- Serial1.println(" The allowed flash address are page 120 (0x801E000) to page 127 (0x0801FFFF)");
- Serial1.println("5. To run, send a command letter followed by the page number (NOTHING between)");
- Serial1.println(" The commands are: 'r' to read, 'u' to unlock, 'w' to write demo array, 'e' to Erase,");
- Serial1.println(" 'l' to lock. Example: r15 to read page 15. w123 to write page 123");
- Serial1.println(" Use 'd' followed by the number of cells to use in the demo. Default is 100");
- Serial1.println("6. To display this text, send 't'. Good luck!");
- Serial1.println();
- }
- /*****************************************************************************/
- void loop()
- /*****************************************************************************/
- {
- delay(500);
- while (Serial1.available()) {
- input = Serial1.read();
- switch(input)
- {
- case 'r': //Read flash page
- page=0;
- while (Serial1.available())
- {
- page = page*10+(Serial1.read()-48); //Convert ASCII to number
- }
- if (page>127)
- {
- Serial1.println();
- Serial1.println("Page >127, out of range");
- return;
- }
- read_flash(page, 0, demo_cells); //read_flash(int page, int offset, int num_cells)
- Serial1.flush();
- break;
- case 'e': //Erase flash page
- page=0;
- while (Serial1.available())
- {
- page = page*10+(Serial1.read()-48); //Convert ASCII to number
- }
- if (page>127 || page<120)
- {
- Serial1.println();
- Serial1.println("Page out of range");
- return;
- }
- erase_flash_page(page);
- Serial1.flush();
- break;
- case 'w': //Write flash page
- page=0;
- while (Serial1.available())
- {
- page = page*10+(Serial1.read()-48); //Convert ASCII to number
- }
- if (page>127 || page<120)
- {
- Serial1.println("Page out of range");
- return;
- }
- write_flash(demo_data, page, 0, demo_cells); //write_flash(int page, int offset, int num_cells)
- Serial1.flush();
- break;
- case 'u': //Unlock flash
- unlock_flash();
- break;
- case 't': //Display startup test message
- startup_message();
- break;
- case 'l':
- lock_flash(); //Lock flash
- break;
- case 'p': //Print out the registers
- print_registers();
- break;
- case 'd': //Number of demo cells to use
- demo_cells=0;
- while (Serial1.available())
- {
- demo_cells = demo_cells*10+(Serial1.read()-48); //Convert ASCII to number
- }
- Serial1.println();
- Serial1.print("Number of demo cells set to ");
- Serial1.println(demo_cells);
- if (demo_cells>1023)
- {
- Serial1.println("Can only use up to 1023 cells");
- demo_cells=1023;
- return;
- }
- Serial1.flush();
- break;
- default:
- Serial1.println("Bad input");
- }
- }
- } //end main loop
- /*****************************************************************************/
- void unlock_flash()
- /*****************************************************************************/
- {
- FLASH_BASE->KEYR = 0x45670123; //The STM Key1
- FLASH_BASE->KEYR = 0xCDEF89AB; //The STM Key2
- //prog halts and bus error is returned on a wrong key sequence
- //must reset to continue.
- if (FLASH_BASE->CR & 1 << 7) //Check if unlocked
- {
- Serial1.println("Flash Unlock error");
- return;
- }
- else Serial1.println();
- Serial1.println("Flash Unlocked");
- } //End unlock_flash
- /*****************************************************************************/
- void lock_flash()
- /*****************************************************************************/
- {
- FLASH_BASE->CR = 0x80; //Reset and lock.
- if (FLASH_BASE->CR & 1<<7) //Check if locked
- {
- Serial1.println();
- Serial1.println("Flash Locked");
- }
- else Serial1.println("Flash Lock error");
- return;
- } //End lock_flash
- /*****************************************************************************
- * Erase one full page at a time. Option to erase all flash
- * The Mass Erase command can be used to completely erase the user pages of the Flash
- * memory. The information block is unaffected by this procedure.
- * not implemented here to avoid accidental erasure.
- ******************************************************************************/
- void erase_flash_page(char page)
- /*****************************************************************************/
- {
- uint16 test_data; //local test data
- if (FLASH_BASE->CR & 1 << 7) //Check if unlocked.
- {
- Serial1.println("Must unlock flash to erase");
- return;
- }
- // Check allowed page erase limits
- FLASH_BASE->CR |= 1<<1; //PER Page Erase bit selected.
- FLASH_BASE->AR =((int)flash_base+page*1024); //Calculate the page base address.
- page = (FLASH_BASE->AR - flash_base) / 1024; //Check by reading back the address register
- if (page >127 || page <100)
- {
- Serial1.println("Page must be between 100 - 127.");
- lock_flash(); // Flash protection emergency brake...
- return;
- }
- Serial1.println();
- Serial1.print("Erasing page ");
- Serial1.println((int)page);
- //Erase selected page
- while ((FLASH_BASE->SR & (1<<0))) {
- } //Check not busy
- FLASH_BASE->CR |= 1<<1; //PER Single Page Erase bit selected.
- // FLASH_BASE->CR |= 1<<2; //MER Mass erase option. Do not try at home!!!
- FLASH_BASE->AR =((int)flash_base+page*1024); // The page address
- FLASH_BASE->CR |= 1<<6; //Set the Erase Start bit
- while (FLASH_BASE->SR & (1<<0)) {
- }
- //Read page to check if all cells were erased (if all set to 'FF')
- for (uint16 i=0;i<1024;i++)
- {
- while (FLASH_BASE->SR & (1<<0)) {
- }
- read_address=(byte*)(flash_base+page*1024+i);
- test_data= *read_address; //flash_data*
- if ((uint8)test_data != 0xFF)
- {
- Serial1.println("Page erase error");
- lock_flash();
- return;
- }
- }
- Serial1.println("Page erased OK");
- lock_flash();
- } //End erase_flash_page
- /*****************************************************************************
- * Read flash byte by byte and load into an array of up to 1024 bytes, which is one
- * Flash page. It combines each two bytes into one 16 bits half-word.
- * The function returns the array and also calls the printout function for the array.
- */
- uint16 read_flash(uint8 page, uint16 offset, uint16 num_cells) //Reads byte by byte
- /*****************************************************************************/
- {
- //Build start address, decimal.
- Serial1.println();
- Serial1.print("Reading page ");
- Serial1.println(page);
- for (int i=offset;i<offset+demo_cells;i=i+2) // Progress memory byte address.
- {
- while (FLASH_BASE->SR & (1<<0)) {
- } //Check not in use
- //Reading the data, combining 2 bytes into one half-word (16 bits). The odd bytes are most significant.
- read_address=(byte*)(flash_base+page*1024+i); //Calculating fist byte address.
- data_address[i]=flash_base+page*1024+i; //Reading first byte
- flash_data[i]= *read_address; //loading first byte to the array.
- read_address=(byte*)(flash_base+page*1024+i+1); //Reading second byte byte
- flash_data[i]= flash_data[i] + (*read_address <<8); //Combining 2 bytes to one 16 bit half-word.
- }
- print_flash(flash_data,data_address); //Call the print function
- return (int)flash_data; //Return array for any use.
- } //End read_flash
- /*****************************************************************************
- * Writes the demo array (built in the setup()) to the selected page at set offset.
- * Can cross page border, but pages must be erased before writing, or write error.
- * Be aware not to extend the memory address beyond end of page 127.
- /*****************************************************************************/
- void write_flash(uint16 demo_data[],char page, uint16 offset, uint16 demo_cells)
- {
- byte test_data;
- boolean error=false;
- if (FLASH_BASE->CR & (1 << 7)) //Check if unlocked.
- {
- Serial1.println();
- Serial1.println("Must unlock flash to write");
- return;
- }
- //Prior to writing, must read cells to check if all cells are erased (if all set to 'FF')
- for (uint16 i=0;i<demo_cells;i++)
- {
- while (FLASH_BASE->SR & (1<<0)) {
- }
- test_data=*((byte*)(flash_base+page*1024+i));
- if (test_data != 0xFF)
- {
- error=true;
- break;
- }
- }
- if(error==true)
- {
- Serial1.println("Page not clear error");
- lock_flash();
- return;
- }
- while ((FLASH_BASE->SR & (1<<0))==true) {
- } //Check not in use
- FLASH_BASE->CR |= 1<<0; //Set PG program bit
- // FLASH_BASE->ACR |=1<<1; //Set latency
- Serial1.println();
- Serial1.print("Attempt writing flash page ");
- Serial1.println((int)page);
- for (uint16 k=0;k<demo_cells;k=k+2) //Jumps 2 bytes per double byte write
- {
- write_address=(uint16*)(flash_base+page*1024+offset+k);
- //Address write protection
- if ((int)write_address < lower_address_limit || (int)write_address > upper_address_limit)
- {
- Serial1.println("Address out of allowed limits. Page not written.");
- lock_flash(); //Wrong address emergency brake...
- return;
- }
- while (FLASH_BASE->SR & (1<<0)) {
- }
- *(uint16*) write_address=demo_data[k];
- // *(uint16*) write_address=0xAA55; //flash_data
- }
- Serial1.println("Writing flash complete");
- lock_flash();
- } //End write_flash
- /*****************************************************************************
- * Print out the flash from read function array.
- * Will print the address of each bytes pair, the byte serial number and the data
- * in 16 bits binary format.
- ******************************************************************************/
- void print_flash(uint16 data[],int data_address[])
- /*****************************************************************************/
- {
- for (uint16 f=0; f<demo_cells;f=f+2)
- {
- Serial1.print(data_address[f],HEX);
- Serial1.print(" ");
- Serial1.print(f);
- Serial1.print(" ");
- Serial1.println(data[f],BIN);
- }
- }
- /*****************************************************************************/
- void print_registers() //For debug, read registers states.
- /*****************************************************************************/
- {
- Serial1.println();
- Serial1.print("Reg SR=");
- Serial1.println(FLASH_BASE->SR,BIN); //Busy bit 0
- Serial1.print("Reg CR=");
- Serial1.println(FLASH_BASE->CR,BIN); //Set PG program bit
- Serial1.print("Reg AR=");
- Serial1.println(FLASH_BASE->AR,HEX); // Last address
- Serial1.print("Reg ACR=");
- Serial1.println(FLASH_BASE->ACR,BIN); //Set latency
- Serial1.print("Reg WRPR=");
- Serial1.println(FLASH_BASE->WRPR,BIN);
- Serial1.println();
- }
Advertisement
Add Comment
Please, Sign In to add comment