1
- /**************************************************************************/
2
- /*!
3
- @file flash_qspi.c
4
- @author hathach (tinyusb.org)
5
-
6
- @section LICENSE
7
-
8
- Software License Agreement (BSD License)
9
-
10
- Copyright (c) 2018, Adafruit Industries (adafruit.com)
11
- All rights reserved.
12
-
13
- Redistribution and use in source and binary forms, with or without
14
- modification, are permitted provided that the following conditions are met:
15
- 1. Redistributions of source code must retain the above copyright
16
- notice, this list of conditions and the following disclaimer.
17
- 2. Redistributions in binary form must reproduce the above copyright
18
- notice, this list of conditions and the following disclaimer in the
19
- documentation and/or other materials provided with the distribution.
20
- 3. Neither the name of the copyright holders nor the
21
- names of its contributors may be used to endorse or promote products
22
- derived from this software without specific prior written permission.
23
-
24
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
25
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
28
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
- */
35
- /**************************************************************************/
1
+ /*
2
+ * The MIT License (MIT)
3
+ *
4
+ * Copyright (c) 2019 Ha Thach for Adafruit Industries
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in
14
+ * all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ * THE SOFTWARE.
23
+ */
36
24
37
25
#ifdef NRF52840_XXAA
38
26
42
30
#include "flash_cache.h"
43
31
#include "nrfx_qspi.h"
44
32
45
- #define _VALID_PIN (n ) (defined(PIN_QSPI_DATA##n) && (PIN_QSPI_DATA##n != 0xff))
46
-
47
- #define QSPI_FLASH_MODE \
48
- (( _VALID_PIN(0) && _VALID_PIN(1) && _VALID_PIN(2) && _VALID_PIN(3) ) ? 4 : \
49
- ( _VALID_PIN(0) && _VALID_PIN(1) ) ? 2 : \
50
- ( _VALID_PIN(0) ) ? 1 : 0)
51
-
52
- #if QSPI_FLASH_MODE
33
+ #ifdef EXTERNAL_FLASH_DEVICES
53
34
54
35
//--------------------------------------------------------------------+
55
36
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
59
40
QSPI_CMD_RSTEN = 0x66 ,
60
41
QSPI_CMD_RST = 0x99 ,
61
42
QSPI_CMD_WRSR = 0x01 ,
62
- QSPI_CMD_READID = 0x90
43
+ QSPI_CMD_REMS = 0x90 ,
63
44
};
64
45
65
- // If Flash device is not specified, support all devices in flash_devices.h
66
- #ifdef EXTERNAL_FLASH_DEVICES
67
46
const qspi_flash_device_t _flash_devices_arr [] = { EXTERNAL_FLASH_DEVICES };
68
- #else
69
- const qspi_flash_device_t _flash_devices_arr [] = { GD25Q16C , MX25R6435F };
70
- #endif
71
-
72
- enum
73
- {
74
- FLASH_DEVICE_COUNT = arrcount (_flash_devices_arr )
75
- };
47
+ enum { FLASH_DEVICE_COUNT = arrcount (_flash_devices_arr ) };
76
48
77
49
const qspi_flash_device_t * _flash_dev = NULL ;
78
50
@@ -85,12 +57,12 @@ static bool fal_qspi_verify (uint32_t addr, void const * buf, uint32_t len);
85
57
static uint8_t _cache_buffer [FLASH_CACHE_SIZE ] __attribute__((aligned (4 )));
86
58
87
59
static flash_cache_t _cache = {
88
- .erase = fal_qspi_erase ,
89
- .program = fal_qspi_program ,
90
- .read = fal_qspi_read ,
91
- .verify = fal_qspi_verify ,
60
+ .erase = fal_qspi_erase ,
61
+ .program = fal_qspi_program ,
62
+ .read = fal_qspi_read ,
63
+ .verify = fal_qspi_verify ,
92
64
.cache_addr = FLASH_CACHE_INVALID_ADDR ,
93
- .cache_buf = _cache_buffer
65
+ .cache_buf = _cache_buffer
94
66
};
95
67
96
68
static SemaphoreHandle_t _qspi_mutex ;
@@ -155,38 +127,25 @@ void flash_qspi_init (void)
155
127
.sck_pin = g_ADigitalPinMap [PIN_QSPI_SCK ],
156
128
.csn_pin = g_ADigitalPinMap [PIN_QSPI_CS ],
157
129
.io0_pin = g_ADigitalPinMap [PIN_QSPI_DATA0 ],
158
- .io1_pin = NRF_QSPI_PIN_NOT_CONNECTED ,
159
- .io2_pin = NRF_QSPI_PIN_NOT_CONNECTED ,
160
- .io3_pin = NRF_QSPI_PIN_NOT_CONNECTED ,
161
-
130
+ .io1_pin = g_ADigitalPinMap [PIN_QSPI_DATA1 ],
131
+ .io2_pin = g_ADigitalPinMap [PIN_QSPI_DATA2 ],
132
+ .io3_pin = g_ADigitalPinMap [PIN_QSPI_DATA3 ],
162
133
},
163
134
.prot_if = {
164
- .readoc = NRF_QSPI_READOC_FASTREAD ,
165
- .writeoc = NRF_QSPI_WRITEOC_PP ,
135
+ .readoc = NRF_QSPI_READOC_READ4IO ,
136
+ .writeoc = NRF_QSPI_WRITEOC_PP4O ,
166
137
.addrmode = NRF_QSPI_ADDRMODE_24BIT ,
167
138
.dpmconfig = false
168
139
},
169
140
.phy_if = {
170
- .sck_freq = NRF_QSPI_FREQ_32MDIV1 ,
171
- .sck_delay = 1 , // min time CS must stay high before going low again. in unit of 62.5 ns
141
+ .sck_freq = NRF_QSPI_FREQ_32MDIV16 , // start with low 2 Mhz speed
142
+ .sck_delay = 10 , // min time CS must stay high before going low again. in unit of 62.5 ns
172
143
.spi_mode = NRF_QSPI_MODE_0 ,
173
144
.dpmen = false
174
145
},
175
146
.irq_priority = 7 ,
176
147
};
177
148
178
- #if QSPI_FLASH_MODE == 2
179
- qspi_cfg .pins .io1_pin = g_ADigitalPinMap [PIN_QSPI_DATA1 ];
180
- qspi_cfg .prot_if .readoc = NRF_QSPI_READOC_READ2IO ;
181
- qspi_cfg .prot_if .writeoc = NRF_QSPI_WRITEOC_PP2O ;
182
- #elif QSPI_FLASH_MODE == 4
183
- qspi_cfg .pins .io1_pin = g_ADigitalPinMap [PIN_QSPI_DATA1 ];
184
- qspi_cfg .pins .io2_pin = g_ADigitalPinMap [PIN_QSPI_DATA2 ];
185
- qspi_cfg .pins .io3_pin = g_ADigitalPinMap [PIN_QSPI_DATA3 ];
186
- qspi_cfg .prot_if .readoc = NRF_QSPI_READOC_READ4IO ;
187
- qspi_cfg .prot_if .writeoc = NRF_QSPI_WRITEOC_PP4O ;
188
- #endif
189
-
190
149
// No callback for blocking API
191
150
nrfx_qspi_init (& qspi_cfg , NULL , NULL );
192
151
@@ -212,25 +171,23 @@ void flash_qspi_init (void)
212
171
NRFX_DELAY_US (100 ); // wait for flash device to reset
213
172
214
173
// Send (Read ID + 3 dummy bytes) + Receive 2 bytes of (Manufacture + Device ID)
215
- uint8_t dummy [6 ] = { 0 };
216
- uint8_t id_resp [6 ] = { 0 };
217
- cinstr_cfg .opcode = QSPI_CMD_READID ;
174
+ uint8_t dummy [5 ] = { 0 };
175
+ uint8_t id_resp [5 ] = { 0 };
176
+ cinstr_cfg .opcode = QSPI_CMD_REMS ;
218
177
cinstr_cfg .length = 6 ;
219
178
220
- // Bug with -nrf_qspi_cinstrdata_get() didn't combine data.
221
- // https://devzone.nordicsemi.com/f/nordic-q-a/38540/bug-nrf_qspi_cinstrdata_get-didn-t-collect-data-from-both-cinstrdat1-and-cinstrdat0
222
179
nrfx_qspi_cinstr_xfer (& cinstr_cfg , dummy , id_resp );
223
180
224
- // Due to the bug, we collect data manually
225
- uint8_t dev_id = (uint8_t ) NRF_QSPI -> CINSTRDAT1 ;
226
- uint8_t mfgr_id = (uint8_t ) ( NRF_QSPI -> CINSTRDAT0 >> 24 );
181
+ uint8_t const mfgr_id = id_resp [3 ];
182
+ uint8_t const dev_id = id_resp [4 ];
227
183
228
184
// quick hack
229
- //printf("qspi mfgr id : 0x%02X\n", mfgr_id);
230
- //printf("qspi device id: 0x%02X\n", dev_id);
185
+ // printf("qspi mfgr id : 0x%02X\n", mfgr_id);
186
+ // printf("qspi device id: 0x%02X\n", dev_id);
187
+ // PRINT_BUFFER(id_resp, sizeof(id_resp));
231
188
232
189
// Look up the flash device in supported array
233
- for ( int i = 0 ; i < FLASH_DEVICE_COUNT ; i ++ )
190
+ for ( uint32_t i = 0 ; i < FLASH_DEVICE_COUNT ; i ++ )
234
191
{
235
192
// Match ID
236
193
if ( _flash_devices_arr [i ].manufacturer_id == mfgr_id && _flash_devices_arr [i ].device_id == dev_id )
@@ -242,13 +199,20 @@ void flash_qspi_init (void)
242
199
243
200
if ( _flash_dev )
244
201
{
245
- // Enable quad mode if needed
246
- #if QSPI_FLASH_MODE == 4
202
+ // Enable quad mode
247
203
cinstr_cfg .opcode = QSPI_CMD_WRSR ;
248
204
cinstr_cfg .length = 3 ;
249
205
cinstr_cfg .wipwait = cinstr_cfg .wren = true;
250
206
nrfx_qspi_cinstr_xfer (& cinstr_cfg , & _flash_dev -> status_quad_enable , NULL );
251
- #endif
207
+
208
+ // Speed up frequency
209
+ nrf_qspi_phy_conf_t phy_if = {
210
+ .sck_freq = _flash_dev -> freq ,
211
+ .sck_delay = 10 ,
212
+ .spi_mode = NRF_QSPI_MODE_0 ,
213
+ .dpmen = false
214
+ };
215
+ nrf_qspi_ifconfig1_set (NRF_QSPI , & phy_if );
252
216
}
253
217
254
218
// create mutex
@@ -284,6 +248,6 @@ static bool fal_qspi_verify (uint32_t addr, void const * buf, uint32_t len)
284
248
return false;
285
249
}
286
250
287
- #endif // valid pin
251
+ #endif // external flash
288
252
#endif // nrf52840
289
253
0 commit comments