Skip to content

Commit bf81926

Browse files
authored
Merge pull request #4058 from LMESTM/17q2_L4_flash
17q2 l4 flash
2 parents 1b2aa9d + 27bff5c commit bf81926

File tree

3 files changed

+255
-4
lines changed

3 files changed

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

targets/targets.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,7 +1062,7 @@
10621062
"inherits": ["Target"],
10631063
"detect_code": ["0770"],
10641064
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"],
1065-
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "CAN", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
1065+
"device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "CAN", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"],
10661066
"release_versions": ["2", "5"],
10671067
"device_name" : "STM32L432KC"
10681068
},
@@ -1075,7 +1075,7 @@
10751075
"inherits": ["Target"],
10761076
"detect_code": ["0765"],
10771077
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2","USBHOST_OTHER"],
1078-
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
1078+
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"],
10791079
"release_versions": ["2", "5"],
10801080
"device_name": "STM32L476RG"
10811081
},
@@ -1088,7 +1088,7 @@
10881088
"inherits": ["Target"],
10891089
"detect_code": ["0827"],
10901090
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2","USBHOST_OTHER"],
1091-
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
1091+
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"],
10921092
"release_versions": ["2", "5"],
10931093
"device_name": "STM32L486RG"
10941094
},
@@ -1242,7 +1242,7 @@
12421242
"supported_toolchains": ["ARM", "uARM", "IAR", "GCC_ARM"],
12431243
"detect_code": ["0820"],
12441244
"macros": ["TRANSACTION_QUEUE_SIZE_SPI=2", "USBHOST_OTHER"],
1245-
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG"],
1245+
"device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"],
12461246
"release_versions": ["2", "5"],
12471247
"device_name": "STM32L476VG"
12481248
},

0 commit comments

Comments
 (0)