32
32
#include " core_esp8266_features.h"
33
33
34
34
#include " spi_utils.h"
35
+ #include " spi_flash_defs.h"
35
36
36
37
extern " C" uint32_t Wait_SPI_Idle (SpiFlashChip *fc);
37
38
@@ -65,6 +66,7 @@ _SPICommand(volatile uint32_t spiIfNum,
65
66
// Everything defined here must be volatile or the optimizer can
66
67
// treat them as constants, resulting in the flash reads we're
67
68
// trying to avoid
69
+ SpiFlashOpResult (* volatile SPI_write_enablep)(SpiFlashChip *) = SPI_write_enable;
68
70
uint32_t (* volatile Wait_SPI_Idlep)(SpiFlashChip *) = Wait_SPI_Idle;
69
71
volatile SpiFlashChip *fchip=flashchip;
70
72
volatile uint32_t spicmdusr=SPICMDUSR;
@@ -85,8 +87,13 @@ _SPICommand(volatile uint32_t spiIfNum,
85
87
uint32_t oldSPI0C = SPIREG (SPI0C);
86
88
87
89
SPIREG (SPI0C) = spic;
90
+
91
+ if (SPI_FLASH_CMD_WREN == pre_cmd) {
92
+ // See SPI_write_enable comments in esp8266_undocumented.h
93
+ SPI_write_enablep ((SpiFlashChip *)fchip);
94
+ } else
88
95
if (pre_cmd) {
89
- // Send prefix cmd w/o data - sends 8 bits - usually a Write Enable cmd
96
+ // Send prefix cmd w/o data - sends 8 bits. eg. Volatile SR Write Enable, 0x50
90
97
SPIREG (SPI0U) = (spiu & ~(SPIUMOSI|SPIUMISO));
91
98
SPIREG (SPI0U1) = 0 ;
92
99
SPIREG (SPI0U2) = (spiu2 & ~0xFFFFu ) | pre_cmd;
@@ -166,25 +173,29 @@ _SPICommand(volatile uint32_t spiIfNum,
166
173
* be separated by SPI Flash read request for iCache, use this option to
167
174
* supply a prefix command, 8-bits w/o read or write data.
168
175
*
176
+ * Case in point from the GD25Q32E datasheet: "The Write Enable for Volatile
177
+ * Status Register command must be issued prior to a Write Status Register
178
+ * command and any other commands can’t be inserted between them."
179
+ *
169
180
* Note: This code has only been tested with SPI bus 0, but should work
170
181
* equally well with other buses. The ESP8266 has bus 0 and 1,
171
182
* newer chips may have more one day.
172
183
*
173
184
* Supplemental Notes:
174
185
*
175
- * SPI Bus view: For *data as an array of bytes, byte[0] goes out first wit
176
- * the most significant bit shifted out first and so on. When thinking of th
177
- * data as an array of 32bit-words, the least significant byte of the first
178
- * 32bit-word goes out first on the SPI bus with the most significant bit of
179
- * that byte shifted out first onto the wire.
186
+ * SPI Bus wire view: Think of *data as an array of bytes, byte[0] goes out
187
+ * first with the most significant bit shifted out first and so on. When
188
+ * thinking of the data as an array of 32bit-words, the least significant byte
189
+ * of the first 32bit-word goes out first on the SPI bus with the most
190
+ * significant bit of that byte shifted out first onto the wire.
180
191
*
181
192
* When presenting a 3 or 4-byte address, the byte order will need to be
182
193
* reversed. Don't overthink it. For a 3-byte address, view *data as a byte
183
194
* array and set the first 3-bytes to the address. eg. byteData[0] MSB,
184
195
* byteData[1] middle, and byteData[2] LSB.
185
196
*
186
197
* When sending a fractional byte, fill in the most significant bit positions
187
- * first.
198
+ * of the byte first.
188
199
*/
189
200
SpiOpResult SPI0Command (uint8_t cmd, uint32_t *data, uint32_t mosi_bits, uint32_t miso_bits, uint32_t pre_cmd) {
190
201
if (mosi_bits>(64 *8 ))
@@ -236,9 +247,16 @@ SpiOpResult SPI0Command(uint8_t cmd, uint32_t *data, uint32_t mosi_bits, uint32_
236
247
SpiOpResult rc =_SPICommand (0 ,spic,spiu,spiu1,spiu2,data,mosi_words,miso_words,pre_cmd);
237
248
238
249
if (rc==SPI_RESULT_OK) {
239
- // clear any bits we did not read in the last word.
240
- if (miso_bits % 32 ) {
241
- data[miso_bits/32 ] &= ~(0xFFFFFFFF << (miso_bits % 32 ));
250
+ // Clear any bits we did not read in the last word. Bits in a fractional
251
+ // bytes will be stored in the most significant part of the byte first.
252
+ if (miso_bits % 32u ) {
253
+ uint32_t whole_byte_bits = (miso_bits % 32u ) & ~7u ;
254
+ uint32_t mask = ~(0xFFFFFFFFu << whole_byte_bits);
255
+ if (miso_bits % 8u ) {
256
+ // Select fractional byte bits.
257
+ mask |= (~(0xFFu >> (miso_bits % 8u )) & 0xFFu ) << whole_byte_bits;
258
+ }
259
+ data[miso_bits/32u ] &= mask;
242
260
}
243
261
}
244
262
return rc;
0 commit comments