Skip to content

Commit 199b130

Browse files
committed
Updated SPIflash to work with Arduino 1.6.x
1 parent 405c8fd commit 199b130

File tree

2 files changed

+67
-31
lines changed

2 files changed

+67
-31
lines changed

libraries/SPIFlash/SPIFlash.cpp

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
* Minimal modifications should allow chips that have different page size but modifications
77
* DEPENDS ON: Arduino SPI library
88
*
9+
* Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment.
10+
* Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
11+
*
912
* This file is free software; you can redistribute it and/or modify
1013
* it under the terms of either the GNU General Public License version 2
1114
* or the GNU Lesser General Public License version 2.1, both as
@@ -32,33 +35,47 @@ SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) {
3235

3336
/// Select the flash chip
3437
void SPIFlash::select() {
35-
noInterrupts();
3638
//save current SPI settings
39+
#ifndef SPI_HAS_TRANSACTION
40+
_SREG = SREG;
41+
noInterrupts();
42+
#endif
3743
_SPCR = SPCR;
3844
_SPSR = SPSR;
39-
//set FLASH chip SPI settings
45+
46+
#ifdef SPI_HAS_TRANSACTION
47+
SPI.beginTransaction(_settings);
48+
#else
49+
// set FLASH SPI settings
4050
SPI.setDataMode(SPI_MODE0);
4151
SPI.setBitOrder(MSBFIRST);
42-
SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
43-
SPI.begin();
52+
SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
53+
#endif
4454
digitalWrite(_slaveSelectPin, LOW);
4555
}
4656

4757
/// UNselect the flash chip
4858
void SPIFlash::unselect() {
4959
digitalWrite(_slaveSelectPin, HIGH);
5060
//restore SPI settings to what they were before talking to the FLASH chip
61+
#ifdef SPI_HAS_TRANSACTION
62+
SPI.endTransaction();
63+
#else
64+
SREG = _SREG; // restore interrupts IFF they were enabled
65+
#endif
5166
SPCR = _SPCR;
5267
SPSR = _SPSR;
53-
interrupts();
5468
}
5569

5670
/// setup SPI, read device ID etc...
5771
boolean SPIFlash::initialize()
5872
{
5973
_SPCR = SPCR;
6074
_SPSR = SPSR;
75+
digitalWrite(_slaveSelectPin, HIGH);
6176
pinMode(_slaveSelectPin, OUTPUT);
77+
SPI.begin();
78+
_settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);
6279
unselect();
6380
wakeup();
6481

@@ -185,22 +202,33 @@ void SPIFlash::writeByte(long addr, uint8_t byt) {
185202
unselect();
186203
}
187204

188-
/// write 1-256 bytes to flash memory
205+
/// write multiple bytes to flash memory (up to 64K)
189206
/// WARNING: you can only write to previously erased memory locations (see datasheet)
190207
/// use the block erase commands to first clear memory (write 0xFFs)
191-
/// WARNING: if you write beyond a page boundary (or more than 256bytes),
192-
/// the bytes will wrap around and start overwriting at the beginning of that same page
193-
/// see datasheet for more details
208+
/// This version handles both page alignment and data blocks larger than 256 bytes.
209+
///
194210
void SPIFlash::writeBytes(long addr, const void* buf, uint16_t len) {
195-
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
196-
SPI.transfer(addr >> 16);
197-
SPI.transfer(addr >> 8);
198-
SPI.transfer(addr);
199-
for (uint16_t i = 0; i < len; i++)
200-
SPI.transfer(((byte*) buf)[i]);
201-
unselect();
211+
uint16_t n;
212+
uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page
213+
uint16_t offset = 0;
214+
while (len>0)
215+
{
216+
n = (len<=maxBytes) ? len : maxBytes;
217+
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
218+
SPI.transfer(addr >> 16);
219+
SPI.transfer(addr >> 8);
220+
SPI.transfer(addr);
221+
for (uint16_t i = 0; i < n; i++)
222+
SPI.transfer(((byte*) buf)[offset + i]);
223+
unselect();
224+
addr+=n; // adjust the addresses and remaining bytes by what we've just transferred.
225+
offset +=n;
226+
len -= n;
227+
maxBytes = 256; // now we can do up to 256 bytes per loop
228+
}
202229
}
203230

231+
204232
/// erase entire flash memory array
205233
/// may take several seconds depending on size, but is non blocking
206234
/// so you may wait for this to complete using busy() or continue doing

libraries/SPIFlash/SPIFlash.h

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
/*
22
* Copyright (c) 2013 by Felix Rusu <[email protected]>
33
* SPI Flash memory library for arduino/moteino.
4-
* This works with 256byte/page SPI flash memory
5-
* For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes)
4+
* This works with 256uint8_t/page SPI flash memory
5+
* For instance a 4MBit (512Kuint8_t) flash chip will have 2048 pages: 256*2048 = 524288 uint8_ts (512Kuint8_ts)
66
* Minimal modifications should allow chips that have different page size but modifications
77
* DEPENDS ON: Arduino SPI library
88
*
9+
* Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
10+
*
911
* This file is free software; you can redistribute it and/or modify
1012
* it under the terms of either the GNU General Public License version 2
1113
* or the GNU Lesser General Public License version 2.1, both as
@@ -56,45 +58,51 @@
5658
// but no actual need to wait for completion (instead need to check the status register BUSY bit)
5759
#define SPIFLASH_STATUSREAD 0x05 // read status register
5860
#define SPIFLASH_STATUSWRITE 0x01 // write status register
59-
#define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy byte after 3 address bytes)
61+
#define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy uint8_t after 3 address uint8_ts)
6062
#define SPIFLASH_ARRAYREADLOWFREQ 0x03 // read array (low frequency)
6163

6264
#define SPIFLASH_SLEEP 0xB9 // deep power down
6365
#define SPIFLASH_WAKE 0xAB // deep power wake up
64-
#define SPIFLASH_BYTEPAGEPROGRAM 0x02 // write (1 to 256bytes)
65-
#define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 bytes, specific bytes for each manufacturer and device)
66+
#define SPIFLASH_BYTEPAGEPROGRAM 0x02 // write (1 to 256uint8_ts)
67+
#define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 uint8_ts, specific uint8_ts for each manufacturer and device)
6668
// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
6769
// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf)
6870
#define SPIFLASH_MACREAD 0x4B // read unique ID number (MAC)
6971

7072
class SPIFlash {
7173
public:
72-
static byte UNIQUEID[8];
73-
SPIFlash(byte slaveSelectPin, uint16_t jedecID=0);
74+
static uint8_t UNIQUEID[8];
75+
SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0);
7476
boolean initialize();
75-
void command(byte cmd, boolean isWrite=false);
76-
byte readStatus();
77-
byte readByte(long addr);
77+
void command(uint8_t cmd, boolean isWrite=false);
78+
uint8_t readStatus();
79+
uint8_t readByte(long addr);
7880
void readBytes(long addr, void* buf, word len);
79-
void writeByte(long addr, byte byt);
81+
void writeByte(long addr, uint8_t byt);
8082
void writeBytes(long addr, const void* buf, uint16_t len);
8183
boolean busy();
8284
void chipErase();
8385
void blockErase4K(long address);
8486
void blockErase32K(long address);
8587
word readDeviceId();
86-
byte* readUniqueId();
88+
uint8_t* readUniqueId();
8789

8890
void sleep();
8991
void wakeup();
9092
void end();
9193
protected:
9294
void select();
9395
void unselect();
94-
byte _slaveSelectPin;
96+
uint8_t _slaveSelectPin;
9597
uint16_t _jedecID;
96-
byte _SPCR;
97-
byte _SPSR;
98+
uint8_t _SPCR;
99+
uint8_t _SPSR;
100+
uint8_t _SREG;
101+
102+
#ifdef SPI_HAS_TRANSACTION
103+
SPISettings _settings;
104+
#endif
105+
98106
};
99107

100108
#endif

0 commit comments

Comments
 (0)