samtal

FlashProgramming.pde

Sep 20th, 2011
681
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.25 KB | None | 0 0
  1.  
  2. /**********************************************************************************
  3.  * @file    FlashProgramming.pde For Maple STM32F1XX Medium 128 KB Flash
  4.  * @author  Samtal
  5.  * @version V1.2.0
  6.  * @date    25-SEP-2011 (added runtime page entry)
  7.  * @brief   Basic flash read / write / erase functions for Maple, Main program body
  8.  *********************************************************************************
  9.  * PLESE READ THESE INSTRUECTIONS
  10.  * WARNING: Writing and erasing flash may cause unpredicted results, including
  11.  * destruction of the boot section and the programs.
  12.  * Make sure you know what you do before start.
  13.  * This sample program enables erasing and writing of pages 120-127 only, but DO NOT
  14.  * rely on the program protection. Remember: Nothing (and no one) is perfect !!
  15.  * The functions used were missing in the original libMaple .h and .c files and are
  16.  * added here as direct registry commands.
  17.  * Communication here is by Serial1 port. If you use USB only, rename all Serial1 to SerialUSB.
  18.  *********************************************************************************/
  19. #include "stdlib.h"      //Included explicitly for proper data printing.
  20. //#include "dma.h"
  21. #include "flash.h"
  22. //#include "flash.c"   //Only contains 2 function (latency and prefetch) that are implemented here
  23.  
  24. //Setting the user's demo parameters:
  25. uint16 demo_data[1024]; //Build the demo array in the setup()
  26. uint16 demo_cells=100;  //Set up the number of demo cells you wish to use for read and write.
  27. byte page=125;          // Set the flash page to use.
  28. byte input;
  29.  
  30. uint16 flash_data[1024];
  31. int flash_base=0x08000000; //= 134217728;
  32. int lower_address_limit = 0x801E000 ;   //Lower safety page limit for the demo Page 120
  33. int upper_address_limit = 0x0801FFFF ;  //Flash upper address. The upper page (127) limit
  34. int data_address[1024];                 // The address array. Used for information only.
  35. byte* read_address;
  36. uint16* write_address;
  37.  
  38. /*****************************************************************************/
  39. void setup()
  40. /*****************************************************************************/
  41. {
  42.   Serial1.begin(56000);     //Optional, if Serial1 is used.
  43.   /* Building demo data array.
  44.    *  Here we build an array starting at 65535, going down by one for each memory location.
  45.    * User may use any other function to build the array.
  46.    */
  47.   for (uint16 d=0;d<demo_cells;d++)
  48.   {
  49.     demo_data[d]=0xFFFF-d;    
  50.     //    Serial1.println(demo_data[d],BIN);    //Optional, for testing
  51.   }
  52.   FLASH_BASE->ACR |= 1<<4;       //ACR bit 4, Prefetch enable.
  53.   FLASH_BASE->ACR |= 1<<1;       //ACR bit 1, Set latency 010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz
  54.  
  55.   startup_message();
  56.  
  57. }  //End Setup
  58.  
  59. /*****************************************************************************/
  60. void startup_message()    //Can be repeated by sending 't'
  61. /*****************************************************************************/
  62. {
  63.   Serial1.println();
  64.   Serial1.println("Welcome to the Flash Read / Write / Erase Demo by samtal");  
  65.   Serial1.println("This program demonstrates the use of the Maple r5 flash programming");
  66.   Serial1.println("Due to the lack of built libMaple functions, This program acts directly on registers");
  67.   Serial1.println("Here are some basic instructions:");
  68.   Serial1.println("1. For safety, the demo is limited to flash pages 120-127 that are normally free,");
  69.   Serial1.println("   but in some occasions may interfere with program.");
  70.   Serial1.println("2. A demo array is built in the setup and used. You may build any other array");
  71.   Serial1.println("3. Each Write or Erase command is automatically followed by flash lock.");
  72.   Serial1.println("   You must unlock (u) the flash prior to Write or Erase command.");
  73.   Serial1.println("4. The start page, offset from start and number of flash cells to use are user defined");
  74.   Serial1.println("   in setup. You may alter the numbers, but do not exceed the flash limits.");
  75.   Serial1.println("   The allowed flash address are page 120 (0x801E000) to page 127 (0x0801FFFF)");  
  76.   Serial1.println("5. To run, send a command letter followed by the page number (NOTHING between)");
  77.   Serial1.println("   The commands are: 'r' to read, 'u' to unlock, 'w' to write demo array, 'e' to Erase,");
  78.   Serial1.println("   'l' to lock.    Example: r15 to read page 15. w123 to write page 123");
  79.   Serial1.println("   Use 'd' followed by the number of cells to use in the demo. Default is 100");
  80.   Serial1.println("6. To display this text, send 't'. Good luck!");
  81.   Serial1.println();
  82. }
  83.  
  84. /*****************************************************************************/
  85. void loop()
  86. /*****************************************************************************/
  87. {
  88.   delay(500);
  89.  
  90.   while (Serial1.available()) {
  91.     input = Serial1.read();
  92.  
  93.     switch(input)
  94.     {
  95.  
  96.     case 'r':           //Read flash page
  97.       page=0;
  98.       while (Serial1.available())
  99.       {
  100.         page = page*10+(Serial1.read()-48);   //Convert ASCII to number
  101.       }
  102.       if (page>127)
  103.       {
  104.         Serial1.println();
  105.         Serial1.println("Page >127, out of range");
  106.         return;
  107.       }
  108.       read_flash(page, 0, demo_cells);  //read_flash(int page, int offset, int num_cells)
  109.       Serial1.flush();  
  110.       break;
  111.  
  112.     case 'e':                          //Erase flash page
  113.       page=0;
  114.       while (Serial1.available())
  115.       {
  116.         page = page*10+(Serial1.read()-48);       //Convert ASCII to number
  117.       }
  118.       if (page>127 || page<120)
  119.       {
  120.         Serial1.println();
  121.         Serial1.println("Page out of range");
  122.         return;
  123.       }
  124.       erase_flash_page(page);
  125.       Serial1.flush();  
  126.       break;
  127.  
  128.     case 'w':                    //Write flash page
  129.       page=0;
  130.       while (Serial1.available())
  131.       {
  132.         page = page*10+(Serial1.read()-48);       //Convert ASCII to number
  133.       }
  134.       if (page>127 || page<120)
  135.       {
  136.         Serial1.println("Page out of range");
  137.         return;
  138.       }
  139.       write_flash(demo_data, page, 0, demo_cells);   //write_flash(int page, int offset, int num_cells)
  140.       Serial1.flush();  
  141.       break;
  142.  
  143.     case 'u':                //Unlock flash
  144.       unlock_flash();
  145.       break;
  146.  
  147.     case 't':                //Display startup test message
  148.       startup_message();
  149.       break;
  150.  
  151.     case 'l':
  152.       lock_flash();          //Lock flash
  153.       break;
  154.  
  155.     case 'p':                //Print out the registers
  156.       print_registers();
  157.       break;
  158.  
  159.     case 'd':              //Number of demo cells to use
  160.     demo_cells=0;
  161.       while (Serial1.available())
  162.       {
  163.         demo_cells = demo_cells*10+(Serial1.read()-48);       //Convert ASCII to number
  164.       }
  165.       Serial1.println();
  166.       Serial1.print("Number of demo cells set to ");
  167.       Serial1.println(demo_cells);
  168.       if (demo_cells>1023)
  169.       {
  170.         Serial1.println("Can only use up to 1023 cells");
  171.         demo_cells=1023;
  172.         return;
  173.       }
  174.      Serial1.flush();  
  175.       break;
  176.      
  177.     default:
  178.       Serial1.println("Bad input");
  179.     }
  180.   }
  181.  
  182. } //end main loop
  183.  
  184. /*****************************************************************************/
  185. void unlock_flash()
  186. /*****************************************************************************/
  187. {
  188.   FLASH_BASE->KEYR = 0x45670123;   //The STM Key1
  189.   FLASH_BASE->KEYR = 0xCDEF89AB;   //The STM Key2
  190.   //prog halts and bus error is returned on a wrong key sequence
  191.   //must reset to continue.
  192.   if (FLASH_BASE->CR & 1 << 7)     //Check if unlocked
  193.   {
  194.     Serial1.println("Flash Unlock error");
  195.     return;
  196.   }
  197.   else Serial1.println();
  198.   Serial1.println("Flash Unlocked");
  199.  
  200. } //End unlock_flash
  201.  
  202. /*****************************************************************************/
  203. void lock_flash()
  204. /*****************************************************************************/
  205. {
  206.   FLASH_BASE->CR = 0x80;      //Reset and lock.
  207.   if (FLASH_BASE->CR & 1<<7)  //Check if locked
  208.   {
  209.     Serial1.println();
  210.     Serial1.println("Flash Locked");
  211.   }
  212.   else Serial1.println("Flash Lock error");
  213.   return;
  214.  
  215. }  //End lock_flash
  216.  
  217. /*****************************************************************************
  218.  * Erase one full page at a time. Option to erase all flash  
  219.  * The Mass Erase command can be used to completely erase the user pages of the Flash
  220.  * memory. The information block is unaffected by this procedure.
  221.  * not implemented here to avoid accidental erasure.
  222.  ******************************************************************************/
  223. void erase_flash_page(char page)    
  224. /*****************************************************************************/
  225. {
  226.   uint16 test_data;      //local test data
  227.  
  228.     if (FLASH_BASE->CR & 1 << 7)      //Check if unlocked.
  229.   {
  230.     Serial1.println("Must unlock flash to erase");
  231.     return;
  232.   }
  233.   // Check allowed page erase limits
  234.   FLASH_BASE->CR |= 1<<1;      //PER Page Erase bit selected.
  235.   FLASH_BASE->AR =((int)flash_base+page*1024);    //Calculate the page base address.
  236.   page = (FLASH_BASE->AR - flash_base) / 1024;     //Check by reading back the address register
  237.   if (page >127 || page <100)
  238.   {
  239.     Serial1.println("Page must be between 100 - 127.");
  240.     lock_flash();         // Flash protection emergency brake...
  241.     return;
  242.   }
  243.   Serial1.println();
  244.   Serial1.print("Erasing page ");  
  245.   Serial1.println((int)page);
  246.  
  247.   //Erase selected page  
  248.   while ((FLASH_BASE->SR & (1<<0))) {
  249.   }     //Check not busy
  250.   FLASH_BASE->CR |= 1<<1;                //PER Single Page Erase bit selected.
  251.   // FLASH_BASE->CR |= 1<<2;             //MER Mass erase option. Do not try at home!!!
  252.   FLASH_BASE->AR =((int)flash_base+page*1024);    // The page address
  253.   FLASH_BASE->CR |= 1<<6;                         //Set the Erase Start bit
  254.   while (FLASH_BASE->SR & (1<<0)) {
  255.   }    
  256.   //Read page to check if all cells were erased (if all set to 'FF')
  257.   for (uint16 i=0;i<1024;i++)
  258.   {
  259.     while (FLASH_BASE->SR & (1<<0)) {
  260.     }
  261.     read_address=(byte*)(flash_base+page*1024+i);  
  262.     test_data= *read_address;     //flash_data*
  263.     if  ((uint8)test_data != 0xFF)
  264.     {
  265.       Serial1.println("Page erase error");
  266.       lock_flash();
  267.       return;
  268.     }
  269.   }
  270.   Serial1.println("Page erased OK");
  271.   lock_flash();
  272. } //End erase_flash_page
  273.  
  274. /*****************************************************************************
  275.  * Read flash byte by byte and load into an array of up to 1024 bytes, which is one
  276.  * Flash page. It combines each two bytes into one 16 bits half-word.
  277.  * The function returns the array and also calls the printout function for the array.
  278.  */
  279. uint16 read_flash(uint8 page, uint16 offset, uint16 num_cells) //Reads byte by byte
  280. /*****************************************************************************/
  281. {
  282.   //Build start address, decimal.
  283.   Serial1.println();
  284.   Serial1.print("Reading page ");
  285.   Serial1.println(page);
  286.   for (int i=offset;i<offset+demo_cells;i=i+2)                // Progress memory byte address.
  287.   {
  288.     while (FLASH_BASE->SR & (1<<0)) {  
  289.     }   //Check not in use
  290.     //Reading the data, combining 2 bytes into one half-word (16 bits). The odd bytes are most significant.
  291.     read_address=(byte*)(flash_base+page*1024+i);            //Calculating fist byte address.
  292.     data_address[i]=flash_base+page*1024+i;                  //Reading first byte
  293.     flash_data[i]= *read_address;                            //loading first byte to the array.
  294.     read_address=(byte*)(flash_base+page*1024+i+1);          //Reading second byte byte
  295.     flash_data[i]= flash_data[i] + (*read_address <<8);      //Combining 2 bytes to one 16 bit half-word.  
  296.   }
  297.   print_flash(flash_data,data_address);                      //Call the print function
  298.   return (int)flash_data;                                    //Return array for any use.
  299.  
  300. } //End read_flash
  301.  
  302. /*****************************************************************************
  303.  * Writes the demo array (built in the setup()) to the selected page at set offset.
  304.  * Can cross page border, but pages must be erased before writing, or write error.
  305.  * Be aware not to extend the memory address beyond end of page 127.
  306. /*****************************************************************************/
  307. void write_flash(uint16 demo_data[],char page, uint16 offset, uint16 demo_cells)
  308. {
  309.   byte test_data;
  310.   boolean error=false;
  311.  
  312.   if (FLASH_BASE->CR & (1 << 7))      //Check if unlocked.
  313.   {
  314.     Serial1.println();
  315.     Serial1.println("Must unlock flash to write");
  316.     return;
  317.   }
  318.  
  319.   //Prior to writing, must read cells to check if all cells are erased (if all set to 'FF')
  320.   for (uint16 i=0;i<demo_cells;i++)
  321.   {
  322.     while (FLASH_BASE->SR & (1<<0)) {
  323.     }  
  324.     test_data=*((byte*)(flash_base+page*1024+i));  
  325.     if  (test_data != 0xFF)
  326.     {
  327.       error=true;
  328.       break;
  329.     }
  330.   }
  331.   if(error==true)
  332.   {
  333.     Serial1.println("Page not clear error");
  334.     lock_flash();
  335.     return;
  336.   }
  337.  
  338.   while ((FLASH_BASE->SR & (1<<0))==true) {
  339.   }     //Check not in use
  340.   FLASH_BASE->CR |= 1<<0;          //Set PG program bit
  341.   //  FLASH_BASE->ACR |=1<<1;     //Set latency
  342.   Serial1.println();
  343.   Serial1.print("Attempt writing flash page ");
  344.   Serial1.println((int)page);
  345.   for (uint16 k=0;k<demo_cells;k=k+2)   //Jumps 2 bytes per double byte write
  346.   {
  347.     write_address=(uint16*)(flash_base+page*1024+offset+k);  
  348.  
  349.     //Address write protection
  350.     if ((int)write_address < lower_address_limit || (int)write_address > upper_address_limit)
  351.     {
  352.       Serial1.println("Address out of allowed limits. Page not written.");
  353.       lock_flash();          //Wrong address emergency brake...
  354.       return;
  355.     }
  356.     while (FLASH_BASE->SR & (1<<0)) {
  357.     }  
  358.     *(uint16*) write_address=demo_data[k];
  359.     //    *(uint16*) write_address=0xAA55;    //flash_data
  360.   }
  361.   Serial1.println("Writing flash complete");
  362.  
  363.   lock_flash();
  364. }  //End write_flash
  365.  
  366. /*****************************************************************************
  367.  * Print out the flash from read function array.
  368.  * Will print the address of each bytes pair, the byte serial number and the data
  369.  * in 16 bits binary format.
  370.  ******************************************************************************/
  371. void print_flash(uint16 data[],int data_address[])    
  372. /*****************************************************************************/
  373. {
  374.   for (uint16 f=0; f<demo_cells;f=f+2)
  375.   {
  376.     Serial1.print(data_address[f],HEX);
  377.     Serial1.print("  ");
  378.     Serial1.print(f);
  379.     Serial1.print("  ");
  380.     Serial1.println(data[f],BIN);
  381.   }
  382. }
  383. /*****************************************************************************/
  384. void print_registers()    //For debug, read registers states.
  385. /*****************************************************************************/
  386. {
  387.   Serial1.println();
  388.   Serial1.print("Reg SR=");
  389.   Serial1.println(FLASH_BASE->SR,BIN);          //Busy bit 0
  390.   Serial1.print("Reg CR=");
  391.   Serial1.println(FLASH_BASE->CR,BIN);          //Set PG program bit
  392.   Serial1.print("Reg AR=");
  393.   Serial1.println(FLASH_BASE->AR,HEX);          // Last address
  394.   Serial1.print("Reg ACR=");
  395.   Serial1.println(FLASH_BASE->ACR,BIN);         //Set latency  
  396.   Serial1.print("Reg WRPR=");
  397.   Serial1.println(FLASH_BASE->WRPR,BIN);
  398.   Serial1.println();
  399. }
Advertisement
Add Comment
Please, Sign In to add comment