Skip to content

Commit e99222a

Browse files
committed
STM32L4 : add Flash API support
1 parent 567dbf7 commit e99222a

File tree

2 files changed

+272
-0
lines changed

2 files changed

+272
-0
lines changed

targets/TARGET_STM/TARGET_STM32L4/common_objects.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ struct i2c_s {
111111
#endif
112112
};
113113

114+
struct flash_s {
115+
/* nothing to be stored for now */
116+
uint32_t dummy;
117+
};
118+
114119
#include "gpio_object.h"
115120

116121
#ifdef __cplusplus
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
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+
/* Private constants --------------------------------------------------------*/
25+
/** @defgroup FLASH_Private_Constants FLASH Private Constants
26+
* @{
27+
*/
28+
#define FLASH_SIZE_DATA_REGISTER ((uint32_t)0x1FFF75E0)
29+
30+
#if defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx)
31+
#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFF)) ? (0x200 << 10) : \
32+
(((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) << 10))
33+
#else
34+
#define FLASH_SIZE ((((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) == 0xFFFF)) ? (0x400 << 10) : \
35+
(((*((uint16_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0FFF)) << 10))
36+
#endif
37+
38+
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx)
39+
#define FLASH_BANK_SIZE (FLASH_SIZE >> 1)
40+
#else
41+
#define FLASH_BANK_SIZE (FLASH_SIZE)
42+
#endif
43+
44+
#define FLASH_PAGE_SIZE ((uint32_t)0x800)
45+
46+
/**
47+
* @brief Gets the page of a given address
48+
* @param Addr: Address of the FLASH Memory
49+
* @retval The page of a given address
50+
*/
51+
static uint32_t GetPage(uint32_t Addr)
52+
{
53+
uint32_t page = 0;
54+
55+
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
56+
{
57+
/* Bank 1 */
58+
page = (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
59+
}
60+
else
61+
{
62+
/* Bank 2 */
63+
page = (Addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
64+
}
65+
66+
return page;
67+
}
68+
69+
/**
70+
* @brief Gets the bank of a given address
71+
* @param Addr: Address of the FLASH Memory
72+
* @retval The bank of a given address
73+
*/
74+
static uint32_t GetBank(uint32_t Addr)
75+
{
76+
uint32_t bank = 0;
77+
78+
if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) {
79+
/* No Bank swap */
80+
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
81+
bank = FLASH_BANK_1;
82+
} else {
83+
bank = FLASH_BANK_2;
84+
}
85+
} else {
86+
/* Bank swap */
87+
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
88+
bank = FLASH_BANK_2;
89+
} else {
90+
bank = FLASH_BANK_1;
91+
}
92+
}
93+
94+
return bank;
95+
}
96+
97+
/** Initialize the flash peripheral and the flash_t object
98+
*
99+
* @param obj The flash object
100+
* @return 0 for success, -1 for error
101+
*/
102+
int32_t flash_init(flash_t *obj)
103+
{
104+
/* Unlock the Flash to enable the flash control register access *************/
105+
HAL_FLASH_Unlock();
106+
return 0;
107+
}
108+
109+
/** Uninitialize the flash peripheral and the flash_t object
110+
*
111+
* @param obj The flash object
112+
* @return 0 for success, -1 for error
113+
*/
114+
int32_t flash_free(flash_t *obj)
115+
{
116+
/* Lock the Flash to disable the flash control register access (recommended
117+
* to protect the FLASH memory against possible unwanted operation) *********/
118+
HAL_FLASH_Lock();
119+
return 0;
120+
}
121+
122+
/** Erase one sector starting at defined address
123+
*
124+
* The address should be at sector boundary. This function does not do any check for address alignments
125+
* @param obj The flash object
126+
* @param address The sector starting address
127+
* @return 0 for success, -1 for error
128+
*/
129+
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
130+
{
131+
uint32_t FirstPage = 0, BankNumber = 0;
132+
uint32_t PAGEError = 0;
133+
FLASH_EraseInitTypeDef EraseInitStruct;
134+
135+
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
136+
137+
return -1;
138+
}
139+
140+
/* Clear OPTVERR bit set on virgin samples */
141+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
142+
/* Get the 1st page to erase */
143+
FirstPage = GetPage(address);
144+
/* MBED HAL erases 1 page / sector at a time */
145+
/* Get the bank */
146+
BankNumber = GetBank(address);
147+
/* Fill EraseInit structure*/
148+
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
149+
EraseInitStruct.Banks = BankNumber;
150+
EraseInitStruct.Page = FirstPage;
151+
EraseInitStruct.NbPages = 1;
152+
153+
/* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
154+
you have to make sure that these data are rewritten before they are accessed during code
155+
execution. If this cannot be done safely, it is recommended to flush the caches by setting the
156+
DCRST and ICRST bits in the FLASH_CR register. */
157+
158+
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
159+
return -1;
160+
} else {
161+
return 0;
162+
}
163+
}
164+
165+
/** Program one page starting at defined address
166+
*
167+
* The page should be at page boundary, should not cross multiple sectors.
168+
* This function does not do any check for address alignments or if size
169+
* is aligned to a page size.
170+
* @param obj The flash object
171+
* @param address The sector starting address
172+
* @param data The data buffer to be programmed
173+
* @param size The number of bytes to program
174+
* @return 0 for success, -1 for error
175+
*/
176+
int32_t flash_program_page(flash_t *obj, uint32_t address,
177+
const uint8_t *data, uint32_t size)
178+
{
179+
uint32_t StartAddress = 0;
180+
181+
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
182+
return -1;
183+
}
184+
185+
if ((size % 8) != 0) {
186+
/* L4 flash devices can only be programmed 64bits/8 bytes at a time */
187+
return -1;
188+
}
189+
190+
/* Program the user Flash area word by word */
191+
StartAddress = address;
192+
193+
/* HW needs an aligned address to program flash, which data
194+
* parameters doesn't ensure */
195+
if ((uint32_t) data % 4 != 0) {
196+
volatile uint64_t data64;
197+
while (address < (StartAddress + size)) {
198+
for (uint8_t i =0; i < 8; i++) {
199+
*(((uint8_t *) &data64) + i) = *(data + i);
200+
}
201+
202+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64) == HAL_OK) {
203+
address = address + 8;
204+
data = data + 8;
205+
} else {
206+
return -1;
207+
}
208+
}
209+
} else { /* case where data is aligned, so let's avoid any copy */
210+
while (address < (StartAddress + size)) {
211+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *((uint64_t*) data)) == HAL_OK) {
212+
address = address + 8;
213+
data = data + 8;
214+
} else {
215+
return -1;
216+
}
217+
}
218+
}
219+
220+
return 0;
221+
}
222+
223+
/** Get sector size
224+
*
225+
* @param obj The flash object
226+
* @param address The sector starting address
227+
* @return The size of a sector
228+
*/
229+
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) {
230+
/* considering 1 sector = 1 page */
231+
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
232+
return MBED_FLASH_INVALID_SIZE;
233+
} else {
234+
return FLASH_PAGE_SIZE;
235+
}
236+
}
237+
238+
/** Get page size
239+
*
240+
* @param obj The flash object
241+
* @param address The page starting address
242+
* @return The size of a page
243+
*/
244+
uint32_t flash_get_page_size(const flash_t *obj) {
245+
/* considering 1 sector = 1 page */
246+
return FLASH_PAGE_SIZE;
247+
}
248+
249+
/** Get start address for the flash region
250+
*
251+
* @param obj The flash object
252+
* @return The start address for the flash region
253+
*/
254+
uint32_t flash_get_start_address(const flash_t *obj) {
255+
return FLASH_BASE;
256+
}
257+
258+
/** Get the flash region size
259+
*
260+
* @param obj The flash object
261+
* @return The flash region size
262+
*/
263+
uint32_t flash_get_size(const flash_t *obj) {
264+
return FLASH_SIZE;
265+
}
266+
267+
#endif

0 commit comments

Comments
 (0)