Skip to content

Commit a47f9b3

Browse files
bcostm0xc0170
authored andcommitted
STM32F0: Add Flash API support
1 parent 6f5d8ff commit a47f9b3

File tree

3 files changed

+236
-3
lines changed

3 files changed

+236
-3
lines changed

targets/TARGET_STM/TARGET_STM32F0/common_objects.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@ struct can_s {
136136
};
137137
#endif
138138

139+
#if DEVICE_FLASH
140+
struct flash_s {
141+
/* nothing to be stored for now */
142+
uint32_t dummy;
143+
};
144+
#endif
145+
139146
#ifdef __cplusplus
140147
}
141148
#endif
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "flash_api.h"
18+
#include "mbed_critical.h"
19+
20+
#if DEVICE_FLASH
21+
#include "mbed_assert.h"
22+
#include "cmsis.h"
23+
24+
#ifndef FLASH_SIZE
25+
#define FLASH_SIZE (uint32_t)(*((uint16_t *)FLASHSIZE_BASE) * 1024U)
26+
#endif
27+
28+
// Minimum number of bytes to be programmed at a time
29+
#define MIN_PROG_SIZE (4U)
30+
31+
/** Initialize the flash peripheral and the flash_t object
32+
*
33+
* @param obj The flash object
34+
* @return 0 for success, -1 for error
35+
*/
36+
int32_t flash_init(flash_t *obj)
37+
{
38+
return 0;
39+
}
40+
41+
/** Uninitialize the flash peripheral and the flash_t object
42+
*
43+
* @param obj The flash object
44+
* @return 0 for success, -1 for error
45+
*/
46+
int32_t flash_free(flash_t *obj)
47+
{
48+
return 0;
49+
}
50+
51+
static int32_t flash_unlock(void)
52+
{
53+
/* Allow Access to Flash control registers and user Falsh */
54+
if (HAL_FLASH_Unlock()) {
55+
return -1;
56+
} else {
57+
return 0;
58+
}
59+
}
60+
61+
static int32_t flash_lock(void)
62+
{
63+
/* Disable the Flash option control register access (recommended to protect
64+
the option Bytes against possible unwanted operations) */
65+
if (HAL_FLASH_Lock()) {
66+
return -1;
67+
} else {
68+
return 0;
69+
}
70+
}
71+
72+
/** Erase one sector starting at defined address
73+
*
74+
* The address should be at sector boundary. This function does not do any check for address alignments
75+
* @param obj The flash object
76+
* @param address The sector starting address
77+
* @return 0 for success, -1 for error
78+
*/
79+
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
80+
{
81+
uint32_t PAGEError = 0;
82+
FLASH_EraseInitTypeDef EraseInitStruct;
83+
int32_t status = 0;
84+
85+
if (!(IS_FLASH_PROGRAM_ADDRESS(address))) {
86+
return -1;
87+
}
88+
89+
if (flash_unlock() != HAL_OK) {
90+
return -1;
91+
}
92+
93+
// Clear Flash status register's flags
94+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR);
95+
96+
/* MBED HAL erases 1 sector at a time */
97+
/* Fill EraseInit structure*/
98+
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
99+
EraseInitStruct.PageAddress = address;
100+
EraseInitStruct.NbPages = 1;
101+
102+
/* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
103+
you have to make sure that these data are rewritten before they are accessed during code
104+
execution. If this cannot be done safely, it is recommended to flush the caches by setting the
105+
DCRST and ICRST bits in the FLASH_CR register. */
106+
107+
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
108+
status = -1;
109+
}
110+
111+
flash_lock();
112+
113+
return status;
114+
}
115+
116+
/** Program one page starting at defined address
117+
*
118+
* The page should be at page boundary, should not cross multiple sectors.
119+
* This function does not do any check for address alignments or if size
120+
* is aligned to a page size.
121+
* @param obj The flash object
122+
* @param address The sector starting address
123+
* @param data The data buffer to be programmed
124+
* @param size The number of bytes to program
125+
* @return 0 for success, -1 for error
126+
*/
127+
int32_t flash_program_page(flash_t *obj, uint32_t address,
128+
const uint8_t *data, uint32_t size)
129+
{
130+
uint32_t StartAddress = 0;
131+
int32_t status = 0;
132+
133+
if (!(IS_FLASH_PROGRAM_ADDRESS(address))) {
134+
return -1;
135+
}
136+
137+
if ((size % MIN_PROG_SIZE) != 0) {
138+
return -1;
139+
}
140+
141+
if (flash_unlock() != HAL_OK) {
142+
return -1;
143+
}
144+
145+
/* Program the user Flash area word by word */
146+
StartAddress = address;
147+
148+
/* HW needs an aligned address to program flash, which data parameter doesn't ensure */
149+
if ((uint32_t) data % 4 != 0) {
150+
151+
volatile uint32_t data32;
152+
while (address < (StartAddress + size) && (status == 0)) {
153+
for (uint8_t i = 0; i < MIN_PROG_SIZE; i++) {
154+
*(((uint8_t *) &data32) + i) = *(data + i);
155+
}
156+
157+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data32) == HAL_OK) {
158+
address = address + MIN_PROG_SIZE;
159+
data = data + MIN_PROG_SIZE;
160+
} else {
161+
status = -1;
162+
}
163+
}
164+
} else { /* case where data is aligned, so let's avoid any copy */
165+
while ((address < (StartAddress + size)) && (status == 0)) {
166+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *((uint32_t*) data)) == HAL_OK) {
167+
address = address + MIN_PROG_SIZE;
168+
data = data + MIN_PROG_SIZE;
169+
} else {
170+
status = -1;
171+
}
172+
}
173+
}
174+
175+
flash_lock();
176+
177+
return status;
178+
}
179+
180+
/** Get sector size
181+
*
182+
* @param obj The flash object
183+
* @param address The sector starting address
184+
* @return The size of a sector (in our case considering 1 sector = 1 page)
185+
*/
186+
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
187+
{
188+
if (!(IS_FLASH_PROGRAM_ADDRESS(address))) {
189+
return MBED_FLASH_INVALID_SIZE;
190+
} else {
191+
return FLASH_PAGE_SIZE;
192+
}
193+
}
194+
195+
/** Get page size
196+
*
197+
* @param obj The flash object
198+
* @param address The page starting address
199+
* @return The size of a page (in our case the minimum programmable size)
200+
*/
201+
uint32_t flash_get_page_size(const flash_t *obj)
202+
{
203+
return MIN_PROG_SIZE;
204+
}
205+
206+
/** Get start address for the flash region
207+
*
208+
* @param obj The flash object
209+
* @return The start address for the flash region
210+
*/
211+
uint32_t flash_get_start_address(const flash_t *obj)
212+
{
213+
return FLASH_BASE;
214+
}
215+
216+
/** Get the flash region size
217+
*
218+
* @param obj The flash object
219+
* @return The flash region size
220+
*/
221+
uint32_t flash_get_size(const flash_t *obj)
222+
{
223+
return FLASH_SIZE;
224+
}
225+
226+
#endif

targets/targets.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@
823823
},
824824
"detect_code": ["0755"],
825825
"macros_add": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\""],
826-
"device_has_add": ["LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH"],
826+
"device_has_add": ["LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"],
827827
"release_versions": ["2", "5"],
828828
"device_name": "STM32F070RB"
829829
},
@@ -841,7 +841,7 @@
841841
},
842842
"detect_code": ["0730"],
843843
"macros_add": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\""],
844-
"device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH"],
844+
"device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"],
845845
"release_versions": ["2", "5"],
846846
"device_name": "STM32F072RB"
847847
},
@@ -859,7 +859,7 @@
859859
},
860860
"detect_code": ["0750"],
861861
"macros_add": ["CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\""],
862-
"device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH"],
862+
"device_has_add": ["ANALOGOUT", "CAN", "LOWPOWERTIMER", "SERIAL_FC", "SERIAL_ASYNCH", "FLASH"],
863863
"release_versions": ["2", "5"],
864864
"device_name": "STM32F091RC"
865865
},

0 commit comments

Comments
 (0)