Skip to content

Commit 698ab6a

Browse files
committed
Added support for FLASH API
1 parent b43ff94 commit 698ab6a

File tree

4 files changed

+320
-0
lines changed

4 files changed

+320
-0
lines changed
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
3+
* Copyright (c) 2017 STMicroelectronics
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include "flash_api.h"
20+
#include "mbed_critical.h"
21+
22+
#if DEVICE_FLASH
23+
#include "mbed_assert.h"
24+
#include "cmsis.h"
25+
26+
/**
27+
* @brief Gets the page of a given address
28+
* @param Addr: Address of the FLASH Memory
29+
* @retval The page of a given address
30+
*/
31+
static uint32_t GetPage(uint32_t Addr)
32+
{
33+
uint32_t page = 0;
34+
35+
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
36+
/* Bank 1 */
37+
page = (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
38+
} else {
39+
/* Bank 2 */
40+
page = (Addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
41+
}
42+
43+
return page;
44+
}
45+
46+
/**
47+
* @brief Gets the bank of a given address
48+
* @param Addr: Address of the FLASH Memory
49+
* @retval The bank of a given address
50+
*/
51+
static uint32_t GetBank(uint32_t Addr)
52+
{
53+
uint32_t bank = 0;
54+
#if defined(SYSCFG_MEMRMP_FB_MODE)
55+
if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) {
56+
/* No Bank swap */
57+
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
58+
bank = FLASH_BANK_1;
59+
} else {
60+
bank = FLASH_BANK_2;
61+
}
62+
} else {
63+
/* Bank swap */
64+
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
65+
bank = FLASH_BANK_2;
66+
} else {
67+
bank = FLASH_BANK_1;
68+
}
69+
}
70+
#else
71+
/* Device like L432KC */
72+
bank = FLASH_BANK_1;
73+
#endif
74+
75+
return bank;
76+
}
77+
78+
/** Initialize the flash peripheral and the flash_t object
79+
*
80+
* @param obj The flash object
81+
* @return 0 for success, -1 for error
82+
*/
83+
int32_t flash_init(flash_t *obj)
84+
{
85+
return 0;
86+
}
87+
88+
/** Uninitialize the flash peripheral and the flash_t object
89+
*
90+
* @param obj The flash object
91+
* @return 0 for success, -1 for error
92+
*/
93+
int32_t flash_free(flash_t *obj)
94+
{
95+
return 0;
96+
}
97+
98+
static int32_t flash_unlock(void)
99+
{
100+
/* Allow Access to Flash control registers and user Falsh */
101+
if (HAL_FLASH_Unlock()) {
102+
return -1;
103+
} else {
104+
return 0;
105+
}
106+
}
107+
108+
static int32_t flash_lock(void)
109+
{
110+
/* Disable the Flash option control register access (recommended to protect
111+
the option Bytes against possible unwanted operations) */
112+
if (HAL_FLASH_Lock()) {
113+
return -1;
114+
} else {
115+
return 0;
116+
}
117+
}
118+
119+
/** Erase one sector starting at defined address
120+
*
121+
* The address should be at sector boundary. This function does not do any check for address alignments
122+
* @param obj The flash object
123+
* @param address The sector starting address
124+
* @return 0 for success, -1 for error
125+
*/
126+
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
127+
{
128+
uint32_t FirstPage = 0, BankNumber = 0;
129+
uint32_t PAGEError = 0;
130+
FLASH_EraseInitTypeDef EraseInitStruct;
131+
int32_t status = 0;
132+
133+
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
134+
135+
return -1;
136+
}
137+
138+
if (flash_unlock() != HAL_OK) {
139+
return -1;
140+
}
141+
142+
/* Clear error programming flags */
143+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
144+
145+
/* Get the 1st page to erase */
146+
FirstPage = GetPage(address);
147+
/* MBED HAL erases 1 page / sector at a time */
148+
/* Get the bank */
149+
BankNumber = GetBank(address);
150+
/* Fill EraseInit structure*/
151+
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
152+
EraseInitStruct.Banks = BankNumber;
153+
EraseInitStruct.Page = FirstPage;
154+
EraseInitStruct.NbPages = 1;
155+
156+
/* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
157+
you have to make sure that these data are rewritten before they are accessed during code
158+
execution. If this cannot be done safely, it is recommended to flush the caches by setting the
159+
DCRST and ICRST bits in the FLASH_CR register. */
160+
161+
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
162+
status = -1;
163+
}
164+
165+
flash_lock();
166+
167+
return status;
168+
}
169+
170+
/** Program one page starting at defined address
171+
*
172+
* The page should be at page boundary, should not cross multiple sectors.
173+
* This function does not do any check for address alignments or if size
174+
* is aligned to a page size.
175+
* @param obj The flash object
176+
* @param address The sector starting address
177+
* @param data The data buffer to be programmed
178+
* @param size The number of bytes to program
179+
* @return 0 for success, -1 for error
180+
*/
181+
int32_t flash_program_page(flash_t *obj, uint32_t address,
182+
const uint8_t *data, uint32_t size)
183+
{
184+
uint32_t StartAddress = 0;
185+
int32_t status = 0;
186+
187+
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
188+
return -1;
189+
}
190+
191+
if ((size % 8) != 0) {
192+
/* L4 flash devices can only be programmed 64bits/8 bytes at a time */
193+
return -1;
194+
}
195+
196+
if (flash_unlock() != HAL_OK) {
197+
return -1;
198+
}
199+
200+
/* Clear error programming flags */
201+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
202+
203+
/* Program the user Flash area word by word */
204+
StartAddress = address;
205+
206+
/* HW needs an aligned address to program flash, which data
207+
* parameters doesn't ensure */
208+
if ((uint32_t) data % 8 != 0) {
209+
volatile uint64_t data64;
210+
while ((address < (StartAddress + size)) && (status == 0)) {
211+
for (uint8_t i = 0; i < 8; i++) {
212+
*(((uint8_t *) &data64) + i) = *(data + i);
213+
}
214+
215+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64)
216+
== HAL_OK) {
217+
address = address + 8;
218+
data = data + 8;
219+
} else {
220+
status = -1;
221+
}
222+
}
223+
} else { /* case where data is aligned, so let's avoid any copy */
224+
while ((address < (StartAddress + size)) && (status == 0)) {
225+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address,
226+
*((uint64_t *) data))
227+
== HAL_OK) {
228+
address = address + 8;
229+
data = data + 8;
230+
} else {
231+
status = -1;
232+
}
233+
}
234+
}
235+
236+
flash_lock();
237+
238+
return status;
239+
}
240+
241+
/** Get sector size
242+
*
243+
* @param obj The flash object
244+
* @param address The sector starting address
245+
* @return The size of a sector
246+
*/
247+
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
248+
{
249+
/* considering 1 sector = 1 page */
250+
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
251+
return MBED_FLASH_INVALID_SIZE;
252+
} else {
253+
return FLASH_PAGE_SIZE;
254+
}
255+
}
256+
257+
/** Get page size
258+
*
259+
* @param obj The flash object
260+
* @param address The page starting address
261+
* @return The size of a page
262+
*/
263+
uint32_t flash_get_page_size(const flash_t *obj)
264+
{
265+
/* Page size is the minimum programable size, which 8 bytes */
266+
return 8;
267+
}
268+
269+
/** Get start address for the flash region
270+
*
271+
* @param obj The flash object
272+
* @return The start address for the flash region
273+
*/
274+
uint32_t flash_get_start_address(const flash_t *obj)
275+
{
276+
return FLASH_BASE;
277+
}
278+
279+
/** Get the flash region size
280+
*
281+
* @param obj The flash object
282+
* @return The flash region size
283+
*/
284+
uint32_t flash_get_size(const flash_t *obj)
285+
{
286+
return FLASH_SIZE;
287+
}
288+
289+
uint8_t flash_get_erase_value(const flash_t *obj)
290+
{
291+
(void)obj;
292+
293+
return 0xFF;
294+
}
295+
296+
#endif

targets/TARGET_STM/TARGET_STM32G4/objects.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,34 @@ struct i2c_s {
118118
#endif
119119
};
120120

121+
struct dac_s {
122+
DACName dac;
123+
PinName pin;
124+
uint32_t channel;
125+
DAC_HandleTypeDef handle;
126+
};
127+
121128
struct analogin_s {
122129
ADC_HandleTypeDef handle;
123130
PinName pin;
124131
uint8_t channel;
125132
};
126133

134+
#if DEVICE_CAN
135+
struct can_s {
136+
CAN_HandleTypeDef CanHandle;
137+
int index;
138+
int hz;
139+
};
140+
#endif
141+
142+
#if DEVICE_FLASH
143+
struct flash_s {
144+
/* nothing to be stored for now */
145+
uint32_t dummy;
146+
};
147+
#endif
148+
127149
struct trng_s {
128150
RNG_HandleTypeDef handle;
129151
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Still to be added: CAN, USBDEVICE, ANALOGOUT, QSPI, CRC(?), TRNG

targets/targets.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15048,6 +15048,7 @@
1504815048
"lpticker_delay_ticks": 0
1504915049
},
1505015050
"device_has_add": [
15051+
"FLASH",
1505115052
"MPU"
1505215053
],
1505315054
"detect_code": [

0 commit comments

Comments
 (0)