-
Notifications
You must be signed in to change notification settings - Fork 2
/
RAK_FlashInterface.h
185 lines (147 loc) · 5.66 KB
/
RAK_FlashInterface.h
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
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 hathach for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef RAK_FlashInterface_H_
#define RAK_FlashInterface_H_
#include <stdbool.h>
#include <stdint.h>
enum
{
SFLASH_CMD_READ = 0x03, // Single Read
SFLASH_CMD_FAST_READ = 0x0B, // Fast Read
SFLASH_CMD_QUAD_READ = 0x6B, // 1 line address, 4 line data
SFLASH_CMD_READ_JEDEC_ID = 0x9f,
SFLASH_CMD_PAGE_PROGRAM = 0x02,
SFLASH_CMD_QUAD_PAGE_PROGRAM = 0x32, // 1 line address, 4 line data
SFLASH_CMD_READ_STATUS = 0x05,
SFLASH_CMD_READ_STATUS2 = 0x35,
SFLASH_CMD_WRITE_STATUS = 0x01,
SFLASH_CMD_WRITE_STATUS2 = 0x31,
SFLASH_CMD_ENABLE_RESET = 0x66,
SFLASH_CMD_RESET = 0x99,
SFLASH_CMD_WRITE_ENABLE = 0x06,
SFLASH_CMD_WRITE_DISABLE = 0x04,
SFLASH_CMD_ERASE_SECTOR = 0x20,
SFLASH_CMD_ERASE_BLOCK = 0xD8,
SFLASH_CMD_ERASE_CHIP = 0xC7,
SFLASH_CMD_4_BYTE_ADDR = 0xB7,
SFLASH_CMD_3_BYTE_ADDR = 0xE9,
};
/// Constant that is (mostly) true to all external flash devices
enum
{
SFLASH_BLOCK_SIZE = 64 * 1024UL,
SFLASH_SECTOR_SIZE = 4 * 1024,
SFLASH_PAGE_SIZE = 256,
};
class RAK_FlashInterface
{
public:
virtual void begin(void) = 0;
virtual void end(void) = 0;
virtual bool supportQuadMode(void) = 0;
/// Set clock speed in hertz
/// @param write_hz Write clock speed in hertz
/// @param read_hz Read clock speed in hertz
virtual void setClockSpeed(uint32_t write_hz, uint32_t read_hz) = 0;
/// Execute a single byte command e.g Reset, Write Enable
/// @param command command code
/// @return true if success
virtual bool runCommand(uint8_t command) = 0;
/// Execute a command with response data e.g Read Status, Read JEDEC
/// @param command command code
/// @param response buffer to hold data
/// @param len number of bytes to read
/// @return true if success
virtual bool readCommand(uint8_t command, uint8_t *response, uint32_t len) = 0;
/// Execute a command with data e.g Write Status,
/// @param command command code
/// @param data writing data
/// @param len number of bytes to read
/// @return true if success
virtual bool writeCommand(uint8_t command, uint8_t const *data, uint32_t len) = 0;
/// Erase external flash by address
/// @param command can be sector erase (0x20) or block erase 0xD8
/// @param address adddress to be erased
/// @return true if success
virtual bool eraseCommand(uint8_t command, uint32_t address) = 0;
/// Read data from external flash contents. Typically it is implemented by
/// quad read command 0x6B
/// @param addr address to read
/// @param buffer buffer to hold data
/// @param len number of byte to read
/// @return true if success
virtual bool readMemory(uint32_t addr, uint8_t *buffer, uint32_t len) = 0;
/// Write data to external flash contents, flash sector must be previously
/// erased first. Typically it uses quad write command 0x32
/// @param addr address to read
/// @param data writing data
/// @param len number of byte to read
/// @return true if success
virtual bool writeMemory(uint32_t addr, uint8_t const *data, uint32_t len) = 0;
void setAddressLength(uint8_t addr_len) { _addr_len = addr_len; }
void setReadCommand(uint8_t cmd_read) { _cmd_read = cmd_read; }
protected:
// Number of bytes for address
uint8_t _addr_len;
// Command use for read operation
uint8_t _cmd_read;
};
// #include "RAK_FlashInterface_SPI.h"
#include "Arduino.h"
#include "SPI.h"
class RAK_FlashInterface_SPI : public RAK_FlashInterface
{
private:
SPIClass *_spi;
uint8_t _ss;
// SAMD21 M0 can write up to 24 Mhz, but can only read reliably with 12 MHz
uint32_t _clock_wr;
uint32_t _clock_rd;
public:
RAK_FlashInterface_SPI(uint8_t ss, SPIClass *spiinterface);
RAK_FlashInterface_SPI(uint8_t ss, SPIClass &spiinterface);
virtual void begin(void);
virtual void end(void);
virtual bool supportQuadMode(void) { return false; }
virtual void setClockSpeed(uint32_t write_hz, uint32_t read_hz);
virtual bool runCommand(uint8_t command);
virtual bool readCommand(uint8_t command, uint8_t *response, uint32_t len);
virtual bool writeCommand(uint8_t command, uint8_t const *data, uint32_t len);
virtual bool eraseCommand(uint8_t command, uint32_t addr);
virtual bool readMemory(uint32_t addr, uint8_t *data, uint32_t len);
virtual bool writeMemory(uint32_t addr, uint8_t const *data, uint32_t len);
private:
void fillAddress(uint8_t *buf, uint32_t addr);
void beginTransaction(uint32_t clock_hz)
{
_spi->beginTransaction(SPISettings(clock_hz, MSBFIRST, SPI_MODE0));
digitalWrite(_ss, LOW);
}
void endTransaction(void)
{
digitalWrite(_ss, HIGH);
_spi->endTransaction();
}
};
#endif /* RAK_FlashInterface_H_ */