Skip to content

Commit 2bb0126

Browse files
authored
Merge pull request arduino#83 from bcmi-labs/codeflash
CodeFlashBlockDevice
2 parents 20cb100 + 07a583b commit 2bb0126

File tree

7 files changed

+604
-18
lines changed

7 files changed

+604
-18
lines changed

extras/e2studioProjects/portenta_h33_lib/configuration.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@
900900
</config>
901901
<config id="config.driver.flash_hp">
902902
<property id="config.driver.flash_hp.param_checking_enable" value="config.flash_hp.param_checking_enable.bsp"/>
903-
<property id="config.driver.flash_hp.param_code_flash_programming_enable" value="config.driver.flash_hp.param_code_flash_programming_enable.disabled"/>
903+
<property id="config.driver.flash_hp.param_code_flash_programming_enable" value="config.driver.flash_hp.param_code_flash_programming_enable.enabled"/>
904904
<property id="config.driver.flash_hp.param_data_flash_programming_enable" value="config.driver.flash_hp.param_data_flash_programming_enable.enabled"/>
905905
</config>
906906
<config id="config.driver.lpm">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
/*
2+
CodeFlashBlockDevice.cpp
3+
Copyright (c) 2023 Arduino SA. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include "CodeFlashBlockDevice.h"
21+
22+
// To enable debug set CF_DBG to 1 and make sure STORAGE_DEBUG is defined
23+
// in Storage/storage_common.h
24+
#define CF_DBG 0
25+
#define CF_MEM_DBG 0
26+
27+
CodeFlashBlockDevice::CodeFlashBlockDevice() :
28+
_cf_address((bd_addr_t)0x00000000),
29+
_cf_size((bd_size_t)0x00200000),
30+
_cf_reg0_size((bd_size_t)BSP_FEATURE_FLASH_HP_CF_REGION0_SIZE),
31+
_cf_reg0_block_size((bd_size_t)BSP_FEATURE_FLASH_HP_CF_REGION0_BLOCK_SIZE),
32+
_cf_reg1_block_size((bd_size_t)BSP_FEATURE_FLASH_HP_CF_REGION1_BLOCK_SIZE),
33+
_cf_read_size((bd_size_t)0x1),
34+
_cf_program_size((bd_size_t)BSP_FEATURE_FLASH_HP_CF_WRITE_SIZE),
35+
_opened(false)
36+
{
37+
FLASH_open = nullptr;
38+
FLASH_write = nullptr;
39+
FLASH_erase = nullptr;
40+
FLASH_blank_check = nullptr;
41+
FLASH_close = nullptr;
42+
#ifdef UNUSED_FSP_API_FUNCTIONS
43+
FLASH_get_info = nullptr;
44+
FLASH_get_status = nullptr;
45+
FLASH_set_window_access = nullptr;
46+
FLASH_clear_window_access = nullptr;
47+
FLASH_set_code_id = nullptr;
48+
FLASH_reset = nullptr;
49+
FLASH_update_ck_freq = nullptr;
50+
FLASH_select_startup_area = nullptr;
51+
FLASH_swap_bank = nullptr;
52+
FLASH_set_callback = nullptr;
53+
#endif
54+
55+
#if (ARDUINO_FLASH_TYPE == LP_FLASH)
56+
FLASH_open = R_FLASH_LP_Open;
57+
FLASH_write = R_FLASH_LP_Write;
58+
FLASH_erase = R_FLASH_LP_Erase;
59+
FLASH_blank_check = R_FLASH_LP_BlankCheck;
60+
FLASH_close = R_FLASH_LP_Close;
61+
#ifdef UNUSED_FSP_API_FUNCTIONS
62+
FLASH_get_info = R_FLASH_LP_InfoGet;
63+
FLASH_get_status = R_FLASH_LP_StatusGet;
64+
FLASH_set_window_access = R_FLASH_LP_AccessWindowSet;
65+
FLASH_clear_window_access = R_FLASH_LP_AccessWindowClear;
66+
FLASH_set_code_id = R_FLASH_LP_IdCodeSet;
67+
FLASH_reset = R_FLASH_LP_Reset;
68+
FLASH_update_ck_freq = R_FLASH_LP_UpdateFlashClockFreq;
69+
FLASH_select_startup_area = R_FLASH_LP_StartUpAreaSelect;
70+
FLASH_swap_bank = R_FLASH_LP_BankSwap;
71+
FLASH_set_callback = R_FLASH_LP_CallbackSet;
72+
#endif
73+
#endif
74+
75+
#if (ARDUINO_FLASH_TYPE == HP_FLASH)
76+
FLASH_open = R_FLASH_HP_Open;
77+
FLASH_write = R_FLASH_HP_Write;
78+
FLASH_erase = R_FLASH_HP_Erase;
79+
FLASH_blank_check = R_FLASH_HP_BlankCheck;
80+
FLASH_close = R_FLASH_HP_Close;
81+
#ifdef UNUSED_FSP_API_FUNCTIONS
82+
FLASH_get_info = R_FLASH_HP_InfoGet;
83+
FLASH_get_status = R_FLASH_HP_StatusGet;
84+
FLASH_set_window_access = R_FLASH_HP_AccessWindowSet;
85+
FLASH_clear_window_access = R_FLASH_HP_AccessWindowClear;
86+
FLASH_set_code_id = R_FLASH_HP_IdCodeSet;
87+
FLASH_reset = R_FLASH_HP_Reset;
88+
FLASH_update_ck_freq = R_FLASH_HP_UpdateFlashClockFreq;
89+
FLASH_select_startup_area = R_FLASH_HP_StartUpAreaSelect;
90+
FLASH_swap_bank = R_FLASH_HP_BankSwap;
91+
FLASH_set_callback = R_FLASH_HP_CallbackSet;
92+
#endif
93+
#endif
94+
95+
_cfg.data_flash_bgo = false;
96+
_cfg.p_callback = nullptr;
97+
_cfg.p_context = nullptr;
98+
_cfg.p_extend = nullptr;
99+
_cfg.ipl = (BSP_IRQ_DISABLED);
100+
_cfg.irq = FSP_INVALID_VECTOR;
101+
_cfg.err_ipl = (BSP_IRQ_DISABLED);
102+
_cfg.err_irq = FSP_INVALID_VECTOR;
103+
}
104+
105+
CodeFlashBlockDevice& CodeFlashBlockDevice::getInstance()
106+
{
107+
static CodeFlashBlockDevice instance;
108+
return instance;
109+
}
110+
111+
CodeFlashBlockDevice::~CodeFlashBlockDevice()
112+
{
113+
114+
}
115+
116+
int CodeFlashBlockDevice::init()
117+
{
118+
return open();
119+
}
120+
121+
int CodeFlashBlockDevice::deinit()
122+
{
123+
return close();
124+
}
125+
126+
int CodeFlashBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
127+
{
128+
return write(buffer, addr, size);
129+
}
130+
131+
int CodeFlashBlockDevice::open()
132+
{
133+
fsp_err_t rv = FSP_ERR_UNSUPPORTED;
134+
135+
if(_opened) {
136+
return (int)FSP_SUCCESS;
137+
}
138+
139+
if(FLASH_open) {
140+
rv = FLASH_open(&_ctrl,&_cfg);
141+
if(rv == FSP_SUCCESS) {
142+
_opened = true;
143+
} else {
144+
debug_if(CF_DBG, "Code flash: open error %d", rv);
145+
}
146+
}
147+
148+
return (int)rv;
149+
}
150+
151+
int CodeFlashBlockDevice::close()
152+
{
153+
fsp_err_t rv = FSP_ERR_UNSUPPORTED;
154+
155+
if(!_opened) {
156+
return (int)FSP_SUCCESS;
157+
}
158+
159+
if(FLASH_close) {
160+
rv = FLASH_close(&_ctrl);
161+
if(rv == FSP_SUCCESS) {
162+
_opened = false;
163+
} else {
164+
debug_if(CF_DBG, "Code flash: close error %d", rv);
165+
}
166+
}
167+
168+
return (int)rv;
169+
}
170+
171+
int CodeFlashBlockDevice::read(void *buffer, bd_addr_t virtual_address, bd_size_t size)
172+
{
173+
fsp_err_t rv = FSP_ERR_UNSUPPORTED;
174+
175+
if(!_opened) {
176+
debug_if(CF_DBG, "Code flash: read, device not open");
177+
return (int)FSP_ERR_NOT_OPEN;
178+
}
179+
180+
if(!buffer) {
181+
debug_if(CF_DBG, "Code flash: read, invalid buffer");
182+
return (int)FSP_ERR_INVALID_POINTER;
183+
}
184+
185+
if(!is_valid_read(virtual_address, size)) {
186+
debug_if(CF_DBG, "Code flash: read, invalid address");
187+
return (int)FSP_ERR_INVALID_ADDRESS;
188+
}
189+
190+
debug_if(CF_DBG, "Code flash: read, address: 0x%x size: %d", _cf_address + virtual_address, size);
191+
uint8_t *source = (uint8_t *)(_cf_address + virtual_address);
192+
memcpy(buffer, source, size);
193+
194+
#if CF_MEM_DBG
195+
debug_if(CF_DBG, "Code flash: read, dump");
196+
debug_mem((uint8_t*)buffer, size);
197+
#endif
198+
199+
return (int)rv;
200+
}
201+
202+
int CodeFlashBlockDevice::write(const void *buffer, bd_addr_t virtual_address, bd_size_t size)
203+
{
204+
fsp_err_t rv = FSP_ERR_UNSUPPORTED;
205+
206+
if(!_opened) {
207+
debug_if(CF_DBG, "Code flash: write, device not open");
208+
return (int)FSP_ERR_NOT_OPEN;
209+
}
210+
211+
if(!buffer) {
212+
debug_if(CF_DBG, "Code flash: write, invalid buffer");
213+
return (int)FSP_ERR_INVALID_POINTER;
214+
}
215+
216+
if((!is_valid_program(virtual_address, size))) {
217+
debug_if(CF_DBG, "Code flash: write, invalid address");
218+
return (int)FSP_ERR_INVALID_ADDRESS;
219+
}
220+
221+
#if CF_MEM_DBG
222+
debug_if(CF_DBG, "Code flash: write, dump");
223+
debug_mem((uint8_t*)buffer, size);
224+
#endif
225+
226+
if(FLASH_write) {
227+
uint32_t address = _cf_address + virtual_address;
228+
debug_if(CF_DBG, "Code flash: write, address: 0x%x size: %d", address, size);
229+
__disable_irq();
230+
rv = FLASH_write(&_ctrl, (uint32_t)buffer, address, (uint32_t)size);
231+
__enable_irq();
232+
if(rv != FSP_SUCCESS) {
233+
debug_if(CF_DBG, "Code flash: write error %d", rv);
234+
}
235+
}
236+
237+
return (int)rv;
238+
}
239+
240+
uint32_t CodeFlashBlockDevice::get_block_starting_address(bd_addr_t virtual_address)
241+
{
242+
return virtual_address & ~(get_erase_size(virtual_address) - 1);
243+
}
244+
245+
int CodeFlashBlockDevice::check_blank(bd_addr_t virtual_address)
246+
{
247+
fsp_err_t rv = FSP_ERR_UNSUPPORTED;
248+
flash_result_t blank_check_result;
249+
250+
if(!_opened) {
251+
return (int)FSP_ERR_NOT_OPEN;
252+
}
253+
254+
uint32_t block_base_addr = _cf_address + get_block_starting_address(virtual_address);
255+
uint32_t block_size = get_erase_size(virtual_address);
256+
257+
if(FLASH_blank_check) {
258+
debug_if(CF_DBG, "Code flash: blank, address: 0x%x size: %d", block_base_addr, block_size);
259+
rv = FLASH_blank_check(&_ctrl, block_base_addr, block_size, &blank_check_result);
260+
}
261+
262+
return (rv == FSP_SUCCESS && blank_check_result == FLASH_RESULT_BLANK) ? BLOCK_DEVICE_OK : (int)rv;
263+
}
264+
265+
int CodeFlashBlockDevice::erase_block(bd_addr_t virtual_address)
266+
{
267+
fsp_err_t rv = FSP_ERR_UNSUPPORTED;
268+
269+
const uint32_t block_base_addr = _cf_address + get_block_starting_address(virtual_address);
270+
271+
if(FLASH_erase) {
272+
debug_if(CF_DBG, "Code flash: erase_block, address: 0x%x num: %d", block_base_addr, 1);
273+
__disable_irq();
274+
rv = FLASH_erase(&_ctrl, block_base_addr, 1);
275+
__enable_irq();
276+
}
277+
278+
return (int)rv;
279+
}
280+
281+
int CodeFlashBlockDevice::erase(bd_addr_t virtual_address, bd_size_t size)
282+
{
283+
fsp_err_t rv = FSP_ERR_UNSUPPORTED;
284+
285+
if(!_opened) {
286+
debug_if(CF_DBG, "Code flash: erase, device not open");
287+
return (int)FSP_ERR_NOT_OPEN;
288+
}
289+
290+
if(!is_valid_erase(virtual_address, size)) {
291+
debug_if(CF_DBG, "Code flash: erase, invalid address");
292+
return (int)FSP_ERR_INVALID_ADDRESS;
293+
}
294+
295+
debug_if(CF_DBG, "Code flash: erase, address: 0x%x size: %d", virtual_address, size);
296+
uint32_t delete_size = 0;
297+
do {
298+
rv = (fsp_err_t)erase_block(virtual_address + delete_size);
299+
if (rv != FSP_SUCCESS) {
300+
debug_if(CF_DBG, "Code flash: erase block, error %d", rv);
301+
}
302+
delete_size += get_erase_size(virtual_address + delete_size);
303+
rv = (fsp_err_t)check_blank(virtual_address + delete_size);
304+
if (rv != FSP_SUCCESS) {
305+
debug_if(CF_DBG, "Code flash: check blank, error %d", rv);
306+
}
307+
} while(rv == FSP_SUCCESS && delete_size < size);
308+
309+
return (int)rv;
310+
}
311+
312+
bd_size_t CodeFlashBlockDevice::get_program_size() const
313+
{
314+
return _cf_program_size;;
315+
}
316+
317+
bd_size_t CodeFlashBlockDevice::get_erase_size() const
318+
{
319+
return _cf_reg0_block_size;
320+
}
321+
322+
bd_size_t CodeFlashBlockDevice::get_erase_size(bd_addr_t addr) const
323+
{
324+
return addr < _cf_reg0_size ? _cf_reg0_block_size : _cf_reg1_block_size;
325+
}
326+
327+
bd_size_t CodeFlashBlockDevice::get_read_size() const
328+
{
329+
return _cf_read_size;
330+
}
331+
332+
bd_size_t CodeFlashBlockDevice::size() const
333+
{
334+
return _cf_size;
335+
}
336+
337+
const char *CodeFlashBlockDevice::get_type() const
338+
{
339+
return "CODEFLASH";
340+
}
341+
342+
bool CodeFlashBlockDevice::is_valid_program(bd_addr_t addr, bd_size_t size) const
343+
{
344+
return (addr % get_program_size() == 0 && size % get_program_size() == 0 && addr + size <= this->size());
345+
}
346+
347+
bool CodeFlashBlockDevice::is_valid_erase(bd_addr_t addr, bd_size_t size) const
348+
{
349+
return (addr % get_erase_size(addr) == 0 && (addr + size) % get_erase_size(addr + size - 1) == 0 && addr + size <= this->size() && addr % get_erase_size(addr) == 0 && size % get_erase_size(addr) == 0);
350+
}

0 commit comments

Comments
 (0)