Skip to content

Commit d332210

Browse files
committed
add power management block device driver
1 parent 72f27ce commit d332210

File tree

4 files changed

+514
-0
lines changed

4 files changed

+514
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2022, Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#ifndef MBED_POWER_MANAGEMENT_BLOCK_DEVICE_H
19+
#define MBED_POWER_MANAGEMENT_BLOCK_DEVICE_H
20+
21+
#include "BlockDevice.h"
22+
#include "platform/mbed_assert.h"
23+
24+
#if COMPONENT_QSPIF
25+
enum {
26+
QSPIF_HIGH_PERFORMANCE_MODE,
27+
QSPIF_LOW_POWER_MODE,
28+
QSPIF_DEEP_DOWN_MODE,
29+
QSPIF_STANDBY_MODE,
30+
};
31+
#endif
32+
33+
namespace mbed {
34+
35+
class PowerManagementBlockDevice : public BlockDevice {
36+
public:
37+
38+
/** Lifetime of the block device
39+
*
40+
* @param bd Block device to wrap as read only
41+
*/
42+
PowerManagementBlockDevice(BlockDevice *bd);
43+
44+
virtual ~PowerManagementBlockDevice();
45+
46+
/** Initialize a block device
47+
*
48+
* @return 0 on success or a negative error code on failure
49+
*/
50+
virtual int init();
51+
52+
/** Deinitialize a block device
53+
*
54+
* @return 0 on success or a negative error code on failure
55+
*/
56+
virtual int deinit();
57+
58+
/** Ensure data on storage is in sync with the driver
59+
*
60+
* @return 0 on success or a negative error code on failure
61+
*/
62+
virtual int sync();
63+
64+
/** Read blocks from a block device
65+
*
66+
* @param buffer Buffer to read blocks into
67+
* @param addr Address of block to begin reading from
68+
* @param size Size to read in bytes, must be a multiple of read block size
69+
* @return 0 on success, negative error code on failure
70+
*/
71+
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
72+
73+
/** Program blocks to a block device
74+
*
75+
* The blocks must have been erased prior to being programmed
76+
*
77+
* @param buffer Buffer of data to write to blocks
78+
* @param addr Address of block to begin writing to
79+
* @param size Size to write in bytes, must be a multiple of program block size
80+
* @return 0 on success, negative error code on failure
81+
*/
82+
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
83+
84+
/** Erase blocks on a block device
85+
*
86+
* The state of an erased block is undefined until it has been programmed,
87+
* unless get_erase_value returns a non-negative byte value
88+
*
89+
* @param addr Address of block to begin erasing
90+
* @param size Size to erase in bytes, must be a multiple of erase block size
91+
* @return 0 on success, negative error code on failure
92+
*/
93+
virtual int erase(bd_addr_t addr, bd_size_t size);
94+
95+
/** Get the size of a readable block
96+
*
97+
* @return Size of a readable block in bytes
98+
*/
99+
virtual bd_size_t get_read_size() const;
100+
101+
/** Get the size of a programmable block
102+
*
103+
* @return Size of a programmable block in bytes
104+
*/
105+
virtual bd_size_t get_program_size() const;
106+
107+
/** Get the size of an erasable block
108+
*
109+
* @return Size of an erasable block in bytes
110+
*/
111+
virtual bd_size_t get_erase_size() const;
112+
113+
/** Get the size of an erasable block given address
114+
*
115+
* @param addr Address within the erasable block
116+
* @return Size of an erasable block in bytes
117+
* @note Must be a multiple of the program size
118+
*/
119+
virtual bd_size_t get_erase_size(bd_addr_t addr) const;
120+
121+
/** Get the value of storage when erased
122+
*
123+
* If get_erase_value returns a non-negative byte value, the underlying
124+
* storage is set to that value when erased, and storage containing
125+
* that value can be programmed without another erase.
126+
*
127+
* @return The value of storage when erased, or -1 if you can't
128+
* rely on the value of erased storage
129+
*/
130+
virtual int get_erase_value() const;
131+
132+
/** Get the total size of the underlying device
133+
*
134+
* @return Size of the underlying device in bytes
135+
*/
136+
virtual bd_size_t size() const;
137+
138+
/** Get the BlockDevice class type.
139+
*
140+
* @return A string represent the BlockDevice class type.
141+
*/
142+
virtual const char *get_type() const;
143+
144+
/** Switch the Block Device power management mode
145+
* @param pm_mode Power management mode of Block Device
146+
* @return 0 on success, negative error code on failure
147+
*/
148+
virtual int switch_power_management_mode(int pm_mode);
149+
150+
private:
151+
BlockDevice *_bd;
152+
};
153+
154+
} // namespace mbed
155+
156+
// Added "using" for backwards compatibility
157+
#ifndef MBED_NO_GLOBAL_USING_DIRECTIVE
158+
using mbed::PowerManagementBlockDevice;
159+
#endif
160+
161+
#endif
162+
163+
/** @}*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2022, Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "blockdevice/PowerManagementBlockDevice.h"
19+
#include "platform/mbed_error.h"
20+
21+
#if COMPONENT_QSPIF
22+
#include "drivers/QSPI.h"
23+
#define QSPI_CMD_WREN 0x06
24+
#define QSPI_CMD_RDCR0 0x15
25+
#define QSPI_CMD_WRSR 0x01
26+
#define QSPI_CMD_RDSR 0x05
27+
#define QSPI_CMD_NOP 0x00
28+
#define QSPI_CMD_DP 0xB9
29+
#define QSPI_LH_BIT_MASK 0x02
30+
31+
mbed::QSPI _qspif(MBED_CONF_QSPIF_QSPI_IO0,
32+
MBED_CONF_QSPIF_QSPI_IO1,
33+
MBED_CONF_QSPIF_QSPI_IO2,
34+
MBED_CONF_QSPIF_QSPI_IO3,
35+
MBED_CONF_QSPIF_QSPI_SCK,
36+
MBED_CONF_QSPIF_QSPI_CSN,
37+
MBED_CONF_QSPIF_QSPI_POLARITY_MODE);
38+
#endif
39+
40+
namespace mbed {
41+
42+
PowerManagementBlockDevice::PowerManagementBlockDevice(BlockDevice *bd)
43+
: _bd(bd)
44+
{
45+
MBED_ASSERT(_bd);
46+
}
47+
48+
PowerManagementBlockDevice::~PowerManagementBlockDevice()
49+
{
50+
deinit();
51+
}
52+
53+
int PowerManagementBlockDevice::init()
54+
{
55+
return _bd->init();
56+
}
57+
58+
int PowerManagementBlockDevice::deinit()
59+
{
60+
return _bd->deinit();
61+
}
62+
63+
int PowerManagementBlockDevice::sync()
64+
{
65+
return _bd->sync();
66+
}
67+
68+
int PowerManagementBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
69+
{
70+
return _bd->read(buffer, addr, size);
71+
}
72+
73+
int PowerManagementBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
74+
{
75+
return _bd->program(buffer, addr, size);
76+
}
77+
78+
int PowerManagementBlockDevice::erase(bd_addr_t addr, bd_size_t size)
79+
{
80+
return _bd->erase(addr, size);
81+
}
82+
83+
bd_size_t PowerManagementBlockDevice::get_read_size() const
84+
{
85+
return _bd->get_read_size();
86+
}
87+
88+
bd_size_t PowerManagementBlockDevice::get_program_size() const
89+
{
90+
return _bd->get_program_size();
91+
}
92+
93+
bd_size_t PowerManagementBlockDevice::get_erase_size() const
94+
{
95+
return _bd->get_erase_size();
96+
}
97+
98+
bd_size_t PowerManagementBlockDevice::get_erase_size(bd_addr_t addr) const
99+
{
100+
return _bd->get_erase_size(addr);
101+
}
102+
103+
int PowerManagementBlockDevice::get_erase_value() const
104+
{
105+
return _bd->get_erase_value();
106+
}
107+
108+
bd_size_t PowerManagementBlockDevice::size() const
109+
{
110+
return _bd->size();
111+
}
112+
113+
const char *PowerManagementBlockDevice::get_type() const
114+
{
115+
if (_bd != NULL) {
116+
return _bd->get_type();
117+
}
118+
119+
return NULL;
120+
}
121+
122+
int PowerManagementBlockDevice::switch_power_management_mode(int pm_mode)
123+
{
124+
#if COMPONENT_QSPIF
125+
qspi_status_t status = QSPI_STATUS_OK ;
126+
uint8_t wren_inst = QSPI_CMD_WREN;
127+
uint8_t sr_reg[3] = {0};
128+
uint8_t rdcr_inst = QSPI_CMD_RDCR0, wrsr_inst = QSPI_CMD_WRSR, rdsr_inst = QSPI_CMD_RDSR;
129+
uint8_t dp_inst = 0;
130+
131+
if (QSPI_STATUS_OK != _qspif.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
132+
0, QSPI_CFG_BUS_SINGLE, 0)) {
133+
return -1;
134+
}
135+
136+
if (QSPI_STATUS_OK != _qspif.command_transfer(wren_inst, -1, NULL, 0, NULL, 0)) {
137+
return -1;
138+
}
139+
140+
switch (pm_mode) {
141+
case QSPIF_HIGH_PERFORMANCE_MODE :
142+
if (QSPI_STATUS_OK != _qspif.command_transfer(rdsr_inst, -1, NULL, 0, (const char *)&sr_reg[0], 1)) {
143+
return -1;
144+
}
145+
146+
if (QSPI_STATUS_OK != _qspif.command_transfer(rdcr_inst, -1, NULL, 0, (const char *)&sr_reg[1], 2)) {
147+
return -1;
148+
}
149+
150+
sr_reg[2] = QSPI_LH_BIT_MASK;
151+
152+
if (QSPI_STATUS_OK != _qspif.command_transfer(wrsr_inst, -1, (const char *)&sr_reg[0], 3, NULL, 0)) {
153+
return -1;
154+
}
155+
break;
156+
case QSPIF_LOW_POWER_MODE :
157+
if (QSPI_STATUS_OK != _qspif.command_transfer(rdsr_inst, -1, NULL, 0, (const char *)&sr_reg[0], 1)) {
158+
return -1;
159+
}
160+
161+
if (QSPI_STATUS_OK != _qspif.command_transfer(rdcr_inst, -1, NULL, 0, (const char *)&sr_reg[1], 2)) {
162+
return -1;
163+
}
164+
165+
sr_reg[2] = 0;
166+
167+
if (QSPI_STATUS_OK != _qspif.command_transfer(wrsr_inst, -1, (const char *)&sr_reg[0], 3, NULL, 0)) {
168+
return -1;
169+
}
170+
break;
171+
case QSPIF_DEEP_DOWN_MODE :
172+
dp_inst = QSPI_CMD_DP;
173+
if (QSPI_STATUS_OK != _qspif.command_transfer(dp_inst, -1, NULL, 0, NULL, 0)) {
174+
return -1;
175+
}
176+
177+
for (int i, k = 0; i < 10000; i++) {
178+
k++;
179+
}
180+
break;
181+
case QSPIF_STANDBY_MODE :
182+
dp_inst = QSPI_CMD_NOP;
183+
if (QSPI_STATUS_OK != _qspif.command_transfer(dp_inst, -1, NULL, 0, NULL, 0)) {
184+
return -1;
185+
}
186+
187+
for (int i, k = 0; i < 10000; i++) {
188+
k++;
189+
}
190+
break;
191+
default :
192+
break;
193+
}
194+
195+
return 0;
196+
#endif
197+
}
198+
199+
} // namespace mbed
200+
201+
/** @}*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright (c) 2022 ARM Limited. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR)
5+
6+
set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../.. CACHE INTERNAL "")
7+
set(TEST_TARGET mbed-storage-blockdevice-power_management_block_device)
8+
9+
include(${MBED_PATH}/tools/cmake/mbed_greentea.cmake)
10+
11+
project(${TEST_TARGET})
12+
13+
mbed_greentea_add_test(
14+
TEST_NAME
15+
${TEST_TARGET}
16+
TEST_SOURCES
17+
main.cpp
18+
TEST_REQUIRED_LIBS
19+
mbed-storage-blockdevice
20+
)
21+

0 commit comments

Comments
 (0)