Skip to content

Commit 95a85a5

Browse files
Matthew Macovskydustin-crossman
authored andcommitted
Create block device for working around a reserved region
Given an underlying block device and the size of the reserved region, a CyReservedRegionBlockDevice will act as the underlying block device but operating only outside of the reserved region. It also allows reading from the reserved region. The reserved region is assumed to start at address 0 in the underlying block device.
1 parent 71d6f84 commit 95a85a5

File tree

2 files changed

+304
-0
lines changed

2 files changed

+304
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/***************************************************************************//**
2+
* \file CyReservedRegionBlockDevice.cpp
3+
*
4+
* \brief
5+
* Block device for working via an underlying block device without altering
6+
* a reserved region.
7+
*
8+
********************************************************************************
9+
* \copyright
10+
* Copyright 2020 Cypress Semiconductor Corporation
11+
* SPDX-License-Identifier: Apache-2.0
12+
*
13+
* Licensed under the Apache License, Version 2.0 (the "License");
14+
* you may not use this file except in compliance with the License.
15+
* You may obtain a copy of the License at
16+
*
17+
* http://www.apache.org/licenses/LICENSE-2.0
18+
*
19+
* Unless required by applicable law or agreed to in writing, software
20+
* distributed under the License is distributed on an "AS IS" BASIS,
21+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22+
* See the License for the specific language governing permissions and
23+
* limitations under the License.
24+
*******************************************************************************/
25+
26+
#include "CyReservedRegionBlockDevice.h"
27+
28+
CyReservedRegionBlockDevice::CyReservedRegionBlockDevice(BlockDevice *underlying_bd, mbed::bd_size_t reserved_region_size)
29+
{
30+
_underlying_bd = underlying_bd;
31+
_reserved_region_size = reserved_region_size;
32+
_reserved_region_end = 0;
33+
}
34+
35+
int CyReservedRegionBlockDevice::init()
36+
{
37+
int status = _underlying_bd->init();
38+
if (status == BD_ERROR_OK)
39+
{
40+
// Round up to start usable region on an erase boundary
41+
// May need to wait until after init() to determine erase size (e.g. QSPI)
42+
_reserved_region_end = _reserved_region_size + get_erase_size() - (_reserved_region_size % get_erase_size());
43+
}
44+
return status;
45+
}
46+
47+
int CyReservedRegionBlockDevice::deinit()
48+
{
49+
int status = _underlying_bd->deinit();
50+
if (status == BD_ERROR_OK)
51+
{
52+
_reserved_region_end = 0;
53+
}
54+
return status;
55+
}
56+
57+
int CyReservedRegionBlockDevice::read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size)
58+
{
59+
return _underlying_bd->read(buffer, addr + _reserved_region_end, size);
60+
}
61+
62+
int CyReservedRegionBlockDevice::program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size)
63+
{
64+
return _underlying_bd->program(buffer, addr + _reserved_region_end, size);
65+
}
66+
67+
int CyReservedRegionBlockDevice::erase(mbed::bd_addr_t addr, mbed::bd_size_t size)
68+
{
69+
return _underlying_bd->erase(addr + _reserved_region_end, size);
70+
}
71+
72+
mbed::bd_size_t CyReservedRegionBlockDevice::get_read_size() const
73+
{
74+
return _underlying_bd->get_read_size();
75+
}
76+
77+
mbed::bd_size_t CyReservedRegionBlockDevice::get_program_size() const
78+
{
79+
return _underlying_bd->get_program_size();
80+
}
81+
82+
mbed::bd_size_t CyReservedRegionBlockDevice::get_erase_size() const
83+
{
84+
return _underlying_bd->get_erase_size();
85+
}
86+
87+
mbed::bd_size_t CyReservedRegionBlockDevice::get_erase_size(mbed::bd_addr_t addr) const
88+
{
89+
return _underlying_bd->get_erase_size(addr + _reserved_region_end);
90+
}
91+
92+
int CyReservedRegionBlockDevice::get_erase_value() const
93+
{
94+
return _underlying_bd->get_erase_value();
95+
}
96+
97+
mbed::bd_size_t CyReservedRegionBlockDevice::size() const
98+
{
99+
return _underlying_bd->size() - _reserved_region_end;
100+
}
101+
102+
const char *CyReservedRegionBlockDevice::get_type() const
103+
{
104+
return _underlying_bd->get_type();
105+
}
106+
107+
int CyReservedRegionBlockDevice::reserved_read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size)
108+
{
109+
if (addr + size > _reserved_region_end || addr % get_read_size() != 0 || size % get_read_size() != 0)
110+
{
111+
return BD_ERROR_DEVICE_ERROR;
112+
}
113+
114+
return _underlying_bd->read(buffer, addr, size);
115+
}
116+
117+
mbed::bd_addr_t CyReservedRegionBlockDevice::reserved_region_end() const
118+
{
119+
return _reserved_region_end;
120+
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/***************************************************************************//**
2+
* \file CyReservedRegionBlockDevice.h
3+
*
4+
* \brief
5+
* Block device for working via an underlying block device without altering
6+
* a reserved region.
7+
*
8+
********************************************************************************
9+
* \copyright
10+
* Copyright 2020 Cypress Semiconductor Corporation
11+
* SPDX-License-Identifier: Apache-2.0
12+
*
13+
* Licensed under the Apache License, Version 2.0 (the "License");
14+
* you may not use this file except in compliance with the License.
15+
* You may obtain a copy of the License at
16+
*
17+
* http://www.apache.org/licenses/LICENSE-2.0
18+
*
19+
* Unless required by applicable law or agreed to in writing, software
20+
* distributed under the License is distributed on an "AS IS" BASIS,
21+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22+
* See the License for the specific language governing permissions and
23+
* limitations under the License.
24+
*******************************************************************************/
25+
26+
#ifndef CY_RESERVED_REGION_BLOCK_DEVICE_H
27+
#define CY_RESERVED_REGION_BLOCK_DEVICE_H
28+
29+
#include "mbed.h"
30+
31+
/**
32+
* Block device for working via an underlying block device without altering
33+
* a reserved region.
34+
*/
35+
class CyReservedRegionBlockDevice : public mbed::BlockDevice {
36+
public:
37+
/**
38+
* Create a CyReservedRegionBlockDevice. The reserved region will be created at the beginning of the external storage.
39+
*
40+
* @param[in] underlying_bd The underlying block device to use
41+
* @param[in] reserved_region_size Size of the reserved region (will be rounded up to the nearest erase size).
42+
*/
43+
CyReservedRegionBlockDevice(BlockDevice *underlying_bd, mbed::bd_size_t reserved_region_size);
44+
45+
/**
46+
* Initialize the block device.
47+
*
48+
* @return 0 on success. A nonzero error code from the underlying block device on failure.
49+
*/
50+
virtual int init() override;
51+
52+
/**
53+
* Deinitialize the block device.
54+
*
55+
* @return 0 on success. A nonzero error code from the underlying block device on failure.
56+
*/
57+
virtual int deinit() override;
58+
59+
/**
60+
* Destruct the block device.
61+
*
62+
* @return 0 on success. A nonzero error code from the underlying block device on failure.
63+
*/
64+
virtual ~CyReservedRegionBlockDevice() override
65+
{
66+
deinit();
67+
}
68+
69+
/**
70+
* Read blocks from the block device.
71+
*
72+
* @param[out] buffer Buffer to write blocks to
73+
* @param[in] addr Address of block to begin reading from
74+
* @param[in] size Size to read in bytes, must be a multiple of read block size
75+
* @return 0 on success. A nonzero error code from the underlying block device on failure.
76+
*/
77+
virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size) override;
78+
79+
/**
80+
* Program blocks to the block device.
81+
*
82+
* The blocks must have been erased prior to being programmed.
83+
*
84+
* @param[in] buffer Buffer of data to write to blocks
85+
* @param[in] addr Address of block to begin writing to
86+
* @param[in] size Size to write in bytes, must be a multiple of program block size
87+
* @return 0 on success. A nonzero error code from the underlying block device on failure.
88+
*/
89+
virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size) override;
90+
91+
/**
92+
* Erase blocks on a block device.
93+
*
94+
* The state of an erased block is undefined until it has been programmed.
95+
*
96+
* @param[in] addr Address of block to begin erasing
97+
* @param[in] size Size to erase in bytes, must be a multiple of erase block size
98+
* @return 0 on success. A nonzero error code from the underlying block device on failure.
99+
*/
100+
virtual int erase(mbed::bd_addr_t addr, mbed::bd_size_t size) override;
101+
102+
/**
103+
* Get the size of a readable block.
104+
*
105+
* @return Size of a readable block in bytes
106+
*/
107+
virtual mbed::bd_size_t get_read_size() const override;
108+
109+
/**
110+
* Get the size of a programmable block.
111+
*
112+
* @return Size of a program block size in bytes
113+
* @note Must be a multiple of the read size.
114+
*/
115+
virtual mbed::bd_size_t get_program_size() const override;
116+
117+
/**
118+
* Get the size of an erasable block.
119+
*
120+
* @return Size of a minimal erase block, common to all regions, in bytes
121+
* @note Must be a multiple of the program size.
122+
*/
123+
virtual mbed::bd_size_t get_erase_size() const override;
124+
125+
/**
126+
* Get the minimal erasable sector size of given address.
127+
*
128+
* @param[in] addr Any address within block queried for erase sector size (can be any address within flash size offset)
129+
* @return Size of minimal erase sector size, in given address region, in bytes
130+
* @note Must be a multiple of the program size.
131+
*/
132+
virtual mbed::bd_size_t get_erase_size(mbed::bd_addr_t addr) const override;
133+
134+
/**
135+
* Get the value of storage byte after it was erased.
136+
*
137+
* If get_erase_value returns a non-negative byte value, the underlying
138+
* storage is set to that value when erased, and storage containing
139+
* that value can be programmed without another erase.
140+
*
141+
* @return The value of storage when erased, or -1 if you can't
142+
* rely on the value of erased storage
143+
*/
144+
virtual int get_erase_value() const override;
145+
146+
/**
147+
* Get the total size of the region of the underlying device available for use.
148+
*
149+
* @return Size of usable region in bytes
150+
*/
151+
152+
virtual mbed::bd_size_t size() const override;
153+
154+
/**
155+
* Get the BlockDevice class type.
156+
*
157+
* @return A string represent the BlockDevice class type.
158+
*/
159+
virtual const char *get_type() const override;
160+
161+
/**
162+
* Read from the reserved region.
163+
*
164+
* @param[out] buffer Buffer to read data into
165+
* @param[in] addr Address to start read from
166+
* @param[in] size Size to read in bytes, must be a multiple of the read block size
167+
* @return 0 on success. A nonzero error code from the underlying block device on failure.
168+
*/
169+
int reserved_read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
170+
171+
/**
172+
* Get the end address of the reserved region.
173+
*
174+
* @return The end address of the reserved region
175+
*/
176+
mbed::bd_addr_t reserved_region_end() const;
177+
178+
private:
179+
BlockDevice *_underlying_bd;
180+
mbed::bd_size_t _reserved_region_size; // Initial size passed in; used in init() to compute _reserved_region_end
181+
mbed::bd_addr_t _reserved_region_end; // Actual used reserved region end; rounded up to nearest erase size
182+
};
183+
184+
#endif /* CY_RESERVED_REGION_BLOCK_DEVICE_H */

0 commit comments

Comments
 (0)