-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.cpp
203 lines (172 loc) · 5.59 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !DEVICE_QSPI
#error [NOT_SUPPORTED] QSPI not supported for this target
#endif
#include "mbed.h"
#include "drivers/QSPI.h"
// for Nordic platforms fast read should be used and the QSPI flash memory start address
// along with the total buffer size need to be 4-byte aligned/divisible by 4
#if TARGET_NORDIC
#define CMD_READ 0x0B // Fast read
#else
#define CMD_READ 0x03
#endif
#define CMD_WRITE 0x02
#define CMD_ERASE 0x20
#define CMD_RDSR 0x5
#define CMD_WREN 0x6
#define CMD_RSTEN 0x66
#define CMD_RST 0x99
#define STATUS_REG_SIZE 2
#define BIT_WIP 0x1
#define BIT_WEL 0x2
#define BUF_SIZE 12
// hardware ssel (where applicable)
QSPI qspi_device(QSPI_FLASH1_IO0, QSPI_FLASH1_IO1, QSPI_FLASH1_IO2, QSPI_FLASH1_IO3, QSPI_FLASH1_SCK, QSPI_FLASH1_CSN); // io0, io1, io2, io3, sclk, ssel
static bool mem_ready()
{
char status_value[STATUS_REG_SIZE] = {0xFF};
int retries = 10000;
bool mem_ready = true;
do {
retries--;
if (QSPI_STATUS_OK != qspi_device.command_transfer(CMD_RDSR, -1, NULL, 0, status_value, STATUS_REG_SIZE)) {
printf("Reading Status Register failed \n");
}
wait_ms(1);
} while ((status_value[0] & BIT_WIP) != 0 && retries);
if ((status_value[0] & BIT_WIP) != 0) {
printf ("mem_ready FALSE: status value = 0x%x\n", (int)status_value[0]);
mem_ready = false;
}
return mem_ready;
}
static int write_enable()
{
char status_value[STATUS_REG_SIZE] = {0};
int status = -1;
if (QSPI_STATUS_OK != qspi_device.command_transfer(CMD_WREN, -1, NULL, 0, NULL, 0)) {
printf("Sending WREN command FAILED \n");
return status;
}
if (false == mem_ready()) {
printf("Device not ready \n");
return status;
}
if (QSPI_STATUS_OK != qspi_device.command_transfer(CMD_RDSR, -1, NULL, 0, status_value, STATUS_REG_SIZE)) {
printf("Reading Status Register failed \n");
return status;
}
if ((status_value[0] & BIT_WEL)) {
status = 0;
}
return status;
}
static int flash_init()
{
int status = QSPI_STATUS_OK;
char status_value[STATUS_REG_SIZE] = {0};
// Read the Status Register from device
status = qspi_device.command_transfer(CMD_RDSR, -1, NULL, 0, status_value, STATUS_REG_SIZE);
if (status != QSPI_STATUS_OK) {
printf("Reading Status Register failed: value = 0x%x\n", (int)status_value[0]);
return status;
}
// Send Reset Enable
status = qspi_device.command_transfer(CMD_RSTEN, -1, NULL, 0, NULL, 0);
if (status == QSPI_STATUS_OK) {
printf("Sending RSTEN Success \n");
} else {
printf("Sending RSTEN failed \n");
return status;
}
if (false == mem_ready()) {
printf("Device not ready \n");
return -1;
}
// Send Reset
status = qspi_device.command_transfer(CMD_RST, -1, NULL, 0, NULL, 0);
if (status == QSPI_STATUS_OK) {
printf("Sending RST Success \n");
} else {
printf("Sending RST failed \n");
return status;
}
if (false == mem_ready()) {
printf("Device not ready \n");
return -1;
}
return status;
}
static int sector_erase(unsigned int flash_addr)
{
if (0 != write_enable()) {
printf("Write Enabe failed \n");
return -1;
}
if (QSPI_STATUS_OK!= qspi_device.command_transfer(CMD_ERASE, (((int)flash_addr) & 0x00FFF000), NULL, 0, NULL, 0))
{
printf("Erase failed\n");
return -1;
}
if (false == mem_ready()) {
printf("Device not ready \n");
return -1;
}
return 0;
}
int main() {
char tx_buf[BUF_SIZE] = { 'h', 'e', 'l', 'l', 'o', '\0' };
char rx_buf[BUF_SIZE] = {0};
size_t buf_len = sizeof(tx_buf);
qspi_status_t result;
uint32_t address = 0x1000;
result = qspi_device.configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE,
QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
if (result != QSPI_STATUS_OK) {
printf("Config format failed\n");
}
if (QSPI_STATUS_OK != flash_init()) {
printf ("Init failed\n");
return -1;
}
if (0 != sector_erase(address)) {
return -1;
}
if (0 != write_enable()) {
printf("Write Enabe failed \n");
return -1;
}
result = qspi_device.write(CMD_WRITE, -1, address, tx_buf, &buf_len);
if (result != QSPI_STATUS_OK) {
printf("Write failed\n");
return result;
}
printf("Write done: %s \n", tx_buf);
if (false == mem_ready()) {
printf("Device not ready \n");
return -1;
}
result = qspi_device.read(CMD_READ, -1, address, rx_buf, &buf_len);
if (result != QSPI_STATUS_OK) {
printf("Read failed\n");
return result;
}
printf ("Data Read = %s\n", rx_buf);
return 0;
}