Skip to content

Commit c3951d8

Browse files
0xc0170c1728p9
authored andcommitted
flash: add FlashIAP class
Flash IAP that provides write/read/program to an internal API. It invokes flash HAL functions. FlashIAP checks for alignments for erase/write/program. HAL functions do not, to avoid duplication per target implementation.
1 parent 9017b2f commit c3951d8

File tree

5 files changed

+330
-33
lines changed

5 files changed

+330
-33
lines changed

drivers/FlashIAP.cpp

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
#include <string.h>
24+
#include "FlashIAP.h"
25+
#include "mbed_assert.h"
26+
27+
28+
#ifdef DEVICE_FLASH
29+
30+
namespace mbed {
31+
32+
SingletonPtr<PlatformMutex> FlashIAP::_mutex;
33+
34+
static inline bool is_aligned(uint32_t number, uint32_t alignment)
35+
{
36+
if ((number % alignment) != 0) {
37+
return false;
38+
} else {
39+
return true;
40+
}
41+
}
42+
43+
FlashIAP::FlashIAP()
44+
{
45+
46+
}
47+
48+
FlashIAP::~FlashIAP()
49+
{
50+
51+
}
52+
53+
int FlashIAP::init()
54+
{
55+
int ret = 0;
56+
_mutex->lock();
57+
if (flash_init(&_flash)) {
58+
ret = -1;
59+
}
60+
_mutex->unlock();
61+
return ret;
62+
}
63+
64+
int FlashIAP::deinit()
65+
{
66+
int ret = 0;
67+
_mutex->lock();
68+
if (flash_free(&_flash)) {
69+
ret = -1;
70+
}
71+
_mutex->unlock();
72+
return ret;
73+
}
74+
75+
76+
int FlashIAP::read(void *buffer, uint32_t addr, uint32_t size)
77+
{
78+
_mutex->lock();
79+
memcpy(buffer, (const void *)addr, size);
80+
_mutex->unlock();
81+
return 0;
82+
}
83+
84+
int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
85+
{
86+
uint32_t page_size = get_page_size();
87+
uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
88+
// addr and size should be aligned to page size, and multiple of page size
89+
// page program should not cross sector boundaries
90+
if ((is_aligned(addr, page_size) == false) ||
91+
(is_aligned(size, page_size) == false) ||
92+
(size < page_size) ||
93+
(((addr % current_sector_size) + size) > current_sector_size)) {
94+
return -1;
95+
}
96+
97+
int ret = 0;
98+
_mutex->lock();
99+
if (flash_program_page(&_flash, addr, (const uint8_t *)buffer, size)) {
100+
ret = -1;
101+
}
102+
_mutex->unlock();
103+
return ret;
104+
}
105+
106+
int FlashIAP::write(const void *buffer, uint32_t addr, uint32_t size)
107+
{
108+
int ret = 0;
109+
// erase will lock
110+
if (erase(addr, size) != 0) {
111+
return -1;
112+
}
113+
_mutex->lock();
114+
ret = program(buffer, addr, size);
115+
_mutex->unlock();
116+
return ret;
117+
}
118+
119+
bool FlashIAP::is_aligned_to_sector(uint32_t addr, uint32_t size)
120+
{
121+
uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
122+
if ((is_aligned(size, current_sector_size) == false) ||
123+
(is_aligned(addr, current_sector_size) == false)) {
124+
return false;
125+
} else {
126+
return true;
127+
}
128+
}
129+
130+
int FlashIAP::erase(uint32_t addr, uint32_t size)
131+
{
132+
uint32_t current_sector_size = 0UL;
133+
134+
if (is_aligned_to_sector(addr, size) == false) {
135+
return -1;
136+
}
137+
138+
int32_t ret = 0;
139+
_mutex->lock();
140+
while (size) {
141+
ret = flash_erase_sector(&_flash, addr);
142+
if (ret != 0) {
143+
ret = -1;
144+
break;
145+
}
146+
current_sector_size = flash_get_sector_size(&_flash, addr);
147+
if (is_aligned_to_sector(addr, size) == false) {
148+
ret = -1;
149+
break;
150+
}
151+
size -= current_sector_size;
152+
addr += current_sector_size;
153+
}
154+
_mutex->unlock();
155+
return ret;
156+
}
157+
158+
uint32_t FlashIAP::get_page_size() const
159+
{
160+
return flash_get_page_size(&_flash);
161+
}
162+
163+
uint32_t FlashIAP::get_sector_size(uint32_t addr) const
164+
{
165+
return flash_get_sector_size(&_flash, addr);
166+
}
167+
168+
uint32_t FlashIAP::get_flash_size() const
169+
{
170+
return flash_get_size(&_flash);
171+
}
172+
173+
}
174+
175+
#endif

drivers/FlashIAP.h

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
#ifndef MBED_FLASHIAP_H
23+
#define MBED_FLASHIAP_H
24+
25+
#ifdef DEVICE_FLASH
26+
27+
#include "flash_api.h"
28+
#include "platform/SingletonPtr.h"
29+
#include "platform/PlatformMutex.h"
30+
31+
namespace mbed {
32+
33+
/** \addtogroup drivers */
34+
/** @{*/
35+
36+
/** Flash IAP driver. It invokes flash HAL functions.
37+
*
38+
* Note Synchronization level: Thread safe
39+
*/
40+
class FlashIAP {
41+
public:
42+
FlashIAP();
43+
~FlashIAP();
44+
45+
/** Initialize a flash IAP device
46+
*
47+
* Should be called once per lifetime of the object.
48+
* @return 0 on success or a negative error code on failure
49+
*/
50+
int init();
51+
52+
/** Deinitialize a flash IAP device
53+
*
54+
* @return 0 on success or a negative error code on failure
55+
*/
56+
int deinit();
57+
58+
/** Read data from a flash device.
59+
*
60+
* This method invokes memcpy - reads number of bytes from the address
61+
*
62+
* @param buffer Buffer to write to
63+
* @param addr Flash address to begin reading from
64+
* @param size Size to read in bytes
65+
* @return 0 on success, negative error code on failure
66+
*/
67+
int read(void *buffer, uint32_t addr, uint32_t size);
68+
69+
/** Write data at defined flash address
70+
*
71+
* A write is equivalent to an erase followed by a program.
72+
*
73+
* @param buffer Buffer of data to be written
74+
* @param addr Address of a page to begin writing to
75+
* @param size Size to write in bytes, must be a multiple of program and sector sizes
76+
* @return 0 on success, negative error code on failure
77+
*/
78+
int write(const void *buffer, uint32_t addr, uint32_t size);
79+
80+
/** Program data to pages
81+
*
82+
* The sectors must have been erased prior to being programmed
83+
*
84+
* @param buffer Buffer of data to be written
85+
* @param addr Address of a page to begin writing to, must be a multiple of program and sector sizes
86+
* @param size Size to write in bytes, must be a multiple of program and sector sizes
87+
* @return 0 on success, negative error code on failure
88+
*/
89+
int program(const void *buffer, uint32_t addr, uint32_t size);
90+
91+
/** Erase sectors
92+
*
93+
* The state of an erased sector is undefined until it has been programmed
94+
*
95+
* @param addr Address of a sector to begin erasing, must be a multiple of the sector size
96+
* @param size Size to erase in bytes, must be a multiple of the sector size
97+
* @return 0 on success, negative error code on failure
98+
*/
99+
int erase(uint32_t addr, uint32_t size);
100+
101+
/** Get the sector size at the defined address
102+
*
103+
* Sector size might differ at address ranges.
104+
* An example <0-0x1000, sector size=1024; 0x10000-0x20000, size=2048>
105+
*
106+
* @return Size of a sector in bytes
107+
*/
108+
uint32_t get_sector_size(uint32_t addr) const;
109+
110+
/** Get the total size of the underlying device
111+
*
112+
* @return Size of the underlying device in bytes
113+
*/
114+
uint32_t get_flash_size() const;
115+
116+
/** Get the program page size
117+
*
118+
* @return Size of a program page in bytes
119+
*/
120+
uint32_t get_page_size() const;
121+
122+
private:
123+
124+
/** Check if address and size are aligned to a sector
125+
*
126+
* @param number Number that should be aligned
127+
* @param alignment Defined alignment for a number to be checked
128+
* @return true on success, false on failure
129+
*/
130+
bool is_aligned_to_sector(uint32_t addr, uint32_t size);
131+
132+
flash_t _flash;
133+
static SingletonPtr<PlatformMutex> _mutex;
134+
};
135+
136+
} /* namespace mbed */
137+
138+
#endif /* DEVICE_FLASH */
139+
140+
#endif /* MBED_FLASHIAP_H */
141+
142+
/** @}*/

hal/TARGET_FLASH_CMSIS_ALGO/flash_common_algo.c

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static uint32_t jump_to_flash_algo[] = {
5454
0xBD3046A9
5555
};
5656

57-
static uint32_t get_sector_index(flash_t *obj, uint32_t address)
57+
static uint32_t get_sector_index(const flash_t *obj, uint32_t address)
5858
{
5959
// check where address belongs to
6060
size_t sector_index = 0;
@@ -110,13 +110,6 @@ int32_t flash_free(flash_t *obj)
110110

111111
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
112112
{
113-
size_t sector_index = get_sector_index(obj, address);
114-
115-
// erase sector boundary
116-
if ((address % obj->target_config->sectors[sector_index].size) != 0) {
117-
return -1;
118-
}
119-
120113
core_util_critical_section_enter();
121114
flash_algo_init(obj, address, MBED_FLASH_ALGO_ERASE);
122115

@@ -137,22 +130,7 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address)
137130

138131

139132
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
140-
{
141-
// write size boundary
142-
if ((address % obj->target_config->page_size) != 0) {
143-
return -1; // TODO return types
144-
}
145-
// size multiple of sectors
146-
if ((size < obj->target_config->page_size) || (size % obj->target_config->page_size != 0)) {
147-
return -1;
148-
}
149-
150-
uint32_t sector_index = get_sector_index(obj, address);
151-
// should not cross sector boundary
152-
if (((address % obj->target_config->sectors[sector_index].size) + size) > obj->target_config->sectors[sector_index].size) {
153-
return -1;
154-
}
155-
133+
{
156134
core_util_critical_section_enter();
157135
flash_algo_init(obj, address, MBED_FLASH_ALGO_PROGRAM);
158136

@@ -172,18 +150,18 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
172150
}
173151

174152

175-
uint32_t flash_get_sector_size(flash_t *obj, uint32_t address)
153+
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
176154
{
177155
uint32_t sector_index = get_sector_index(obj, address);
178156
return obj->target_config->sectors[sector_index].size;
179157
}
180158

181-
uint32_t flash_get_page_size(flash_t *obj)
159+
uint32_t flash_get_page_size(const flash_t *obj)
182160
{
183161
return obj->target_config->page_size;
184162
}
185163

186-
uint32_t flash_get_size(flash_t *obj)
164+
uint32_t flash_get_size(const flash_t *obj)
187165
{
188166
return obj->target_config->flash_size;
189167
}

0 commit comments

Comments
 (0)