blockos / arduino-dataflash Goto Github PK
View Code? Open in Web Editor NEWSupport for Atmel Dataflash for the Arduino
Home Page: http://blockos.github.com/arduino-dataflash
Support for Atmel Dataflash for the Arduino
Home Page: http://blockos.github.com/arduino-dataflash
Add return values so that we can check for invalid arguments (for example when the chip has only one buffer).
See #17
Write a proper README and fill the wiki with examples.
Currently only non p.o.t buffer size is supported.
See #17
Reading the datasheet for the AT45DB04D chip it talks about padding the stream with 4 "dont care" bits in between the opcode and the page address:
Main Memory Page Read
A Main Memory Page Read allows the user to read data directly from any one of the 2048 pages in the main memory, bypassing both of the data buffers and leaving the contents of the buffers unchanged.
To start a page read, an opcode of 52H or D2H must be clocked into the device fol-lowed by 24 address bits and 32 don’t care bits.
The first four bits of the 24-bit address sequence are reserved bits, the next 11 address bits (PA10 - PA0) specify the page address,and the next nine address bits (BA8 - BA0) specify the starting byte address within the page.
How are the "first four bits" handled below?
for this chip, m_buffersize comes out to 9, and therefore the inline function pageToHiU8 equates to 16-9 and 16-8 for pageToLoU8.
I'm just a bit confused how we're handling the four empty bits for this 4 megabit chip...
void DataFlash::pageRead(uint16_t page, uint16_t offset)
{
reEnable(); // Reset command decoder.
/* Send opcode */
SPI.transfer(DATAFLASH_PAGE_READ);
/* Address (page | offset) */
SPI.transfer(pageToHiU8(page)); // aka page >> 7
SPI.transfer(pageToLoU8(page) | (uint8_t)(offset >> 8)); // aka page << 1 | offset>>8
SPI.transfer((uint8_t)(offset & 0xff));
/* 4 "don't care" bytes */
SPI.transfer(0);
SPI.transfer(0);
SPI.transfer(0);
SPI.transfer(0);
// Can't disable the chip here!
}
Hi, i am trying to interfacing AT45DB041D with arduino uno.
I am trying to upload pagetest code from your library, but i am unable to get any result on serial monitor i am getting 0 value for all outputs.
Add tests to validate address computation. Maybe do this in the form of a set of unit tests.
The BufferToPage method currently initiates the ram -> flash transfer and blocks until completion. this should be reversed. the reason the device has two ram buffers is so that you could continuously write data to it without having the consumer wait for the flush operation.
it should be
function BufferToPage(number)
while (busy) wait;
initiateTransfer(number)
return
and the operations that read flash directly should wait as well. this way, if i'm writing a chunk of data that's larget than the ram buffer, i can initiate the flush, pop out, switch ram buffers and keep writing. the time necessary to flush a buffer to flash is less than the time necessary to fill a ram buffer.
Methods to be tested:
See if adding the following methods/classes improves the usability:
I've used the library with a AT45DB011D and an Uno successfully, but when using with a Mega2650 I get nothing returned from the read status register command. I found I have to use a CS pin other than the Mega2650 SPI SS pin which is pin 53.
As chip erase seems to be buggy, there are suspicions that sector erase may be buggy as well.
Create a subdirectory for tests and move DataFlash_test.cpp there.
See #17
Hi! I'm trying to interface an Arduino Leonardo to an AT45DB041E, but I seem to never be able to write to it, as it always gets stuch waiting for the device to get ready:
SPI.begin();
flash.setup(1);
flash.begin();
flash.bufferWrite(1, 0); // Aways gets stuck here
for(int i=0;i < 256; i++)
{
SPI.transfer(0x00);
}
flash.bufferToPage(1, 0);
Any idea what am I doing wrong?
Find what are the differences between the D and the new E serie.
AT45DB161E datasheet
Use Arduino SPI library. If the host version doesn't support it (too old) the old code may be use. It maybe wise to prompt a warning message telling the user that it may be wise to update his version.
Ref:
I'm using a Teensy 3.1 and a AT45DB161D. For some reason, the very first status code read from the chip always returns 0. This causes the dataflash library to misinitialize its member variables and subsequently, most functions don't work as expected. I've narrowed it down to the SPI mode: with SPI mode 0, it works. With SPI mode 3, the first status code is 0 and subsequent status codes are good.
Therefore two suggestions for dataflash:
Below is a small example program to reproduce (only shows the first status code):
uint8_t st;
void setup() {
Serial.begin(9600);
// initialize SPI
pinMode(MY_SCS, OUTPUT);
digitalWrite(MY_SCS, HIGH);
SPI.begin();
SPI.setDataMode(SPI_MODE3); // NO
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV2);
// enable chip
digitalWrite(MY_SCS, LOW);
// status
SPI.transfer(0xd7);
st = SPI.transfer(0);
// disable chip
digitalWrite(MY_SCS, HIGH);
}
void loop() {
Serial.println(st, HEX);
delay(1000);
}
Add documentation to the Readme file.
Generate the doxygen doc and put it in the wiki.
The Due SPI library has support for auto handling of the chip select. See: http://arduino.cc/en/Reference/DueExtendedSPI
It would be good to get the library firstly working on the Due and then maybe optimize sections for it.
Thanks,
Greg
I am using an AT45DB161E.
After reviewing the manual I can not find any significant difference to the AT45DB161D
Sector erase works correctly with blocks 1 to 15 and not with sectors 0a and 0b.
The issue seems to originate in sectorErase
void DataFlash::sectorErase(int8_t sector)
{
/* Wait for the end of the previous operation. */
waitUntilReady();
reEnable();
/* Send opcode */
SPI.transfer(DATAFLASH_SECTOR_ERASE); // 0x7C
if((sector == AT45_SECTOR_0A) || (sector == AT45_SECTOR_0B))
{
SPI.transfer(0x00);
if(sector == AT45_SECTOR_0A) SPI.transfer(0x00); else SPI.transfer(32);
//SPI.transfer((static_cast<uint8_t>(-sector) & 0x01) << (m_bufferSize - 5));
}
else
{
uint8_t shift = m_bufferSize + m_pageSize - m_sectorSize - 16;
SPI.transfer(sector << shift);
SPI.transfer(0x00);
}
SPI.transfer(0x00);
/* Start sector erase.
The chip remains busy until this operation finishes. */
disable();
}
In the documentation, the E chip sector erase appears functionally the same to the D chip,
The AT45_SECTOR_0A/0B section appears to yield the correct values of 32 and 0, but allocates them to the wrong sector. Sector -1 shoud be 0 and sector 0, 32.
My replacement line "if(sector == AT45_SECTOR_0A) SPI.transfer(0x00); else SPI.transfer(32)" fixes the issue.
Here is my flash_SectorErase:
// flash_sectorErase
/*
* mini, mega
* pin1(misi) to mosi 11, 51
* pin2(sck ) to sck 13, 52
* pin3(rest) to reset 8, 8
* pin4(sc ) to cS 10, 53
* pin5(wp ) to wp 7, 7
* pin6 Vcc 3v3
* pin7 gnd 0v
* pin8(miso) to misi 12, 50
*/
#include <SPI.h>
#include "DataFlash.h"
#if defined(__AVR_ATmega2560__)
static const int csPin= 53; // mega
#else
static const int csPin= 10;
#endif
static const int resetPin = 8;
static const int wpPin= 7;
DataFlash dataflash;
uint8_t currentSector;
static const uint16_t bufferSize[7] = { 264, 264, 264, 264, 528, 528, 528 };
static const uint16_t pagesSector0b[7] = { 120, 120, 248, 248, 248, 120, 248 };
static const uint16_t pagesPerSector[7] = { 128, 128, 256, 256, 256, 128, 256 };
void setup(){
Serial.begin(115200);
delay(1000);
/* Initialize SPI */
SPI.begin();
delay(10);
/* Initialize dataflash */
dataflash.setup(csPin, resetPin, wpPin);
delay(10);
dataflash.begin();
delay(10);
Serial.print("Manual buffer erase : on\n");
dataflash.manualErase();
flashInfo();
int8_t res = 0;
res += testSectorErase(AT45_SECTOR_0A);
res += testSectorErase(AT45_SECTOR_0B);
for(uint8_t i=1; i<16; i++) res += testSectorErase(i);
Serial.print("\nTest ");
if(res != 17) Serial.println("failed!"); else Serial.println("successful!");
delay(2000);
testAll(); // check each byte = 0xFF
}
void fillPages(uint16_t pageStart, uint16_t pageCount, uint16_t bufferSize){
uint8_t myBuffer = 0;
uint16_t page = 0;
for(page=pageStart; page<(pageStart+pageCount); page++){
dataflash.bufferWrite(myBuffer, 0);
for(uint16_t j=0; j<bufferSize; j++)SPI.transfer( j & 0xff );
dataflash.bufferToPage(myBuffer, page);
int8_t res = dataflash.isPageEqualBuffer(page, myBuffer);
if(res == 0){
Serial.print("Page ");
Serial.print(page);
Serial.print(" failed to fill");
}
myBuffer ^= 1; // toggle buffer 0 and 1
}
}
void setBuffer(uint8_t thisBuffer, uint8_t val, uint16_t bufSize){
dataflash.bufferWrite(thisBuffer, 0);
for(uint16_t i=0; i<bufSize; i++) SPI.transfer(val);
}
int8_t testSectorErase(int8_t sectorId){//int8_t ?
uint16_t pageStart, pageCount;
uint8_t thisStatus = dataflash.status();
uint8_t deviceIndex = ((thisStatus & 0x38) >> 3) - 1;
if(sectorId == AT45_SECTOR_0A){
pageStart = 0;
pageCount = 8;
}
else if(sectorId == AT45_SECTOR_0B){
pageStart = 8;
pageCount = pagesSector0b[deviceIndex];
}
else
{
pageStart = pagesPerSector[deviceIndex] * static_cast<uint16_t>(sectorId);
pageCount = pagesPerSector[deviceIndex];
}
Serial.print("\nTesting sector "); Serial.println(sectorId);
Serial.print("Page start ");Serial.print(pageStart);
Serial.print(" Page count "); Serial.println(pageCount);
Serial.print("Filling pages\n");
fillPages(pageStart, pageCount, bufferSize[deviceIndex]);
Serial.println("Erasing sector");
dataflash.sectorErase(sectorId);
Serial.println("Check pages");
uint16_t res = checkPages(pageStart, pageCount, deviceIndex);
if(res != pageCount){
Serial.print("\nFAILURE! ("); Serial.print(res);Serial.print(" out of ");
Serial.print(pageCount); Serial.println(")");
return 0;
}
return 1;
}
uint16_t checkPages(uint16_t pageStart, uint16_t pageCount, uint8_t deviceIndex){
uint16_t count = 0;
int8_t res;
setBuffer(0, 0xFF, bufferSize[deviceIndex]); // fill buffer 0 with 0xFF
for(uint16_t page = pageStart; page < (pageCount+pageStart); page++){
res = dataflash.isPageEqualBuffer(page, 0);
Serial.print("Page "); Serial.print(page);
if(res == 1) {
count++;
Serial.println(" was succesfully erased.");
}else Serial.println (" was not properly erased.");
}
return count;
}
void testAll(){
unsigned long errcount = 0;
int pcount = 0;
Serial.println("\nTest all:");
for (int pagecount = 0; pagecount <4095; pagecount++){//4096
dataflash.pageRead(pagecount,0);
pcount = 0;
Serial.print("Page ");Serial.print(pagecount);
//Serial.println();
for(int i=0; i< DF_45DB161_PAGESIZE; i++){ // 528
uint8_t data = SPI.transfer(0xff);
if (data != 255) {
//Serial.print(i);Serial.print(" ");
//Serial.print( (char)data);
//Serial.print(" "); Serial.println(data);
errcount ++;
pcount++;
}
}
if(pcount > 0) {
Serial.print(" Page error ");Serial.println(pcount);
} else Serial.println();
}
Serial.print("Error count ");Serial.println(errcount);
}
void flashInfo(){
/* Read status register */
uint8_t myStatus = dataflash.status();
DataFlash::ID id;
/* Read manufacturer and device ID */
dataflash.readID(id);
/* Display status register */
Serial.print("Status register :");
Serial.println(myStatus, BIN);
/* Display manufacturer and device ID */
Serial.print("Manufacturer ID : "); // Should be 00011111
Serial.println(id.manufacturer, HEX);
Serial.print("Device ID (part 1) : "); // Should be 00011111
Serial.println(id.device[0], HEX);
Serial.print("Device ID (part 2) : "); // Should be 00000000
Serial.println(id.device[1], HEX);
Serial.print("Extended Device Information String Length : "); // 00000000
Serial.println(id.extendedInfoLength, HEX);
}
void loop(){
}
David
It would be cool to support the whole AT45 family. The infos are already there.
Additional task: find some AT45 chips (other than the at45db161d). Hum... and if the whole family is supported, the class may be renamed at45dxxx.h or something like that.
Ref:
I tried to compile the pageTest sketch for Uno and it gave the error:
test/Dummy.h: No such file or directory
Here is the full output:
C:\Program Files (x86)\Arduino\libraries\arduino-dataflash\DataFlash_test.cpp:4:24: fatal error: test/Dummy.h: No such file or directory
#include "test/Dummy.h"
^
compilation terminated.
exit status 1
Error compiling for board Arduino/Genuino Uno.
Hi,
I'm working on porting your library to Energia (MSP430 Arduino like IDE). Another point : it's a version E (not a D but what are the differences ?)
After very few changements, seems to be OK except one point : pageRead() does not work reading page 0.And I can't explain why ... It's ok this other pages or using pageToBuffer()+bufferRead().
Check that the alternative chip erase implementation. ref
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.