CuVoodoo STM32F1 firmware template
flash_internal.c
Go to the documentation of this file.
1 /* This program is free software: you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License as published by
3  * the Free Software Foundation, either version 3 of the License, or
4  * (at your option) any later version.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program. If not, see <http://www.gnu.org/licenses/>.
13  *
14  */
21 /* standard libraries */
22 #include <stdint.h> // standard integer types
23 #include <stdlib.h> // general utilities
24 
25 /* STM32 (including CM3) libraries */
26 #include <libopencm3/stm32/desig.h> // device signature utilities
27 #include <libopencm3/stm32/flash.h> // flash utilities
28 
29 #include "flash_internal.h" // flash storage library API
30 #include "global.h" // global definitions
31 
33 #define PAGE_SIZE 1024
34 
35 bool flash_internal_read(uint32_t address, uint8_t *buffer, size_t size)
36 {
37  // verify it's in the storage area
38  if (address<STORAGE_START || (address+size)>STORAGE_END) {
39  return false;
40  }
41  if (buffer==NULL || size==0) {
42  return false;
43  }
44 
45  // copy data byte per byte
46  // a more efficient way would be to copy words, than the remaining bytes
47  for (size_t i=0; i<size; i++) {
48  buffer[i] = *((uint8_t*)address+i);
49  }
50 
51  return true;
52 }
53 
54 bool flash_internal_write(uint32_t address, uint8_t *buffer, size_t size)
55 {
56  // verify it's in the storage area
57  if (address<STORAGE_START || (address+size)>STORAGE_END) {
58  return false;
59  }
60  if (buffer==NULL || size==0) {
61  return false;
62  }
63 
64  uint8_t page[PAGE_SIZE]; // the complete page to write
65 
66  flash_unlock(); // unlock flash to be able to write it
67  // go through memory
68  while (size) {
69  uint32_t page_pre = address%PAGE_SIZE; // the beginning data size in the page
70  address -= page_pre; // go to beginning of the page
71  storage_read(address, &page[0], page_pre); // copy existing data
72  if (size>=PAGE_SIZE-page_pre) { // no need to read tailing page data
73  for (uint16_t i=0; i<PAGE_SIZE-page_pre; i++) { // put buffer in page
74  page[page_pre+i] = buffer[i];
75  }
76  buffer += PAGE_SIZE-page_pre; // adjust remaining buffer
77  size -= PAGE_SIZE-page_pre; // adjust remaining size
78  } else { // need read tailing page data
79  for (uint16_t i=0; i<size; i++) { // put buffer in page
80  page[page_pre+i] = buffer[i];
81  }
82  buffer += size; // adjust remaining buffer
83  storage_read(address+page_pre+size, &page[page_pre+size], PAGE_SIZE-page_pre-size); // read tailing page data
84  size = 0; // adjust remaining size
85  }
86 
87  // write page
88  flash_erase_page(address); // erase current page
89  if (flash_get_status_flags()!=FLASH_SR_EOP) { // operation went wrong
90  flash_lock(); // lock back flash to protect it
91  return false;
92  }
93  for (uint16_t i=0; i<PAGE_SIZE/2; i++) { // write whole page
94  flash_program_half_word(address+i*2, *((uint16_t*)page+i));
95  if (flash_get_status_flags()!=FLASH_SR_EOP) { // operation went wrong
96  flash_lock(); // lock back flash to protect it
97  return false;
98  }
99  if (*((uint16_t*)address+i)!=*((uint16_t*)page+i)) { // verify the programmed data is right
100  flash_lock(); // lock back flash to protect it
101  return false;
102  }
103  }
104 
105  address += PAGE_SIZE; // go to next page
106 
107  }
108  flash_lock(); // lock back flash to protect it
109 
110  return true;
111 }
#define STORAGE_START
the start of the flash area where to store data (be sure it&#39;s after the firmware data) ...
global definitions and methods (API)
library to read/write internal flash (API)
bool flash_internal_read(uint32_t address, uint8_t *buffer, size_t size)
read data from internal flash
#define PAGE_SIZE
the flash page size (medium-density devices have 1KiB page size)
#define STORAGE_END
the end of the flash area where to store data
bool flash_internal_write(uint32_t address, uint8_t *buffer, size_t size)
write data to internal flash