where : ibrtses embedded
AVR Pascal (AVRCo) interfacing to Atmel Dataflash
Being part of a logger project the following code gives a hint on how a dataflash is accessed. The project had an ADC sampling contionously with 500Hz and the data had to be written continously. The 10ms write time for a single sector is countered with two internal RAM sector buffers. One was written to by the ADC, while the other was copied to the flash.
{$IDATA}
const
FlashBufferSize:byte= 32;
type
DFBufferT = Array[0..FlashBufferSize-1]of byte;
var
DFState:byte;
DFCmdBuffer:Array[1..8] of byte; // cmd A1 A2 A3 opt1 opt2 opt3 opt4
DFCmdSize:byte;
DFData:byte; // single byte read
DFStatus:byte; // holds the FlashSize !!
DFWriteIndex:LongWord; // index into the flash = DFBufferIndex + DFPage
DFBuffer:byte; // which buffer
DFBlock:word; // which block
DFPage[@DFWriteIndex+2]:word; // which page
DFBufferIndex[@DFWriteIndex]:word; // into the buffer
DFBufferSelect:byte; // which buffer is in use 0 or 1
DFReadBuffer:DFBufferT;
DFWriteBuffer:DFBufferT;
DFWBCount:byte;
DFWriteLen:byte;
FlashWriteLen:byte;
FlashReadLen:byte;
FlashWritePtr:byte;
FlashReadPtr:byte;
ADWriteCount:word; // counts the number of writes for the RTC
// -------------------------- Dataflash ---------------------------------
// SPIMode = 0 meaning
// SCLK = low
// clock in data on rising slope
// clock out data on falling slope
// DF_SO[@PortC,0]:bit; //
// DF_SI[@PortC,1]:bit; //
// DF_Sck[@PortC,2]:bit; // idle = 0
// DF_CS[@PortC,3]:bit; // selected = 0
// DF_WP[@PortC,4]:bit; // protected = 0
// DF_Reset[@PortC,5]:bit; // idle = 0
// DF_RDY[@PortC,6]:bit; //
// DFWriteIndex:LongWord; // index into the flash
// DFBuffer:byte; // which buffer
// DFBlock:word; // which block
// DFPage:word; // which page
// DFBufferIndex:word; // into the buffer
// DFState:byte;
// DFCmdBuffer:Array[1..8] of byte; // cmd A1 A2 A3 opt1 opt2 opt3 opt4
// DFCmdSize:byte;
// initial : CS is high
// final : CS is lo !!!
procedure WriteDFCmd; // DFCmdBuffer has cmd, DFCmd is #bytes
var i,j,k:byte;
begin
DF_Sck:=0;
DF_CS:=1;
DF_WP:=1;
DF_CS:=0;
for i:=1 to DFCmdSize do
k:=DFCmdBuffer[i];
for j:=1 to 8 do
if ((k and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
DF_Sck:=1; // pulse high
k:=k shl 1;
DF_Sck:=0; // default = low
endfor;
endfor;
end;
procedure ReadDFData; // cmd was clocked in, now read a single byte
var j,k:byte;
begin
k:=0;
for j:=1 to 8 do
//if ((k and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
k:=k shl 1;
DF_Sck:=1; // pulse high
If (DF_SO=true) then k:=k or $01; else k:=k and $FE; endif;
DF_Sck:=0; // default = low
endfor;
DFData:=k;
end; // ReadDFData
procedure ReadDFStatus;
begin
DFCmdBuffer[1]:=$57; // inactive clock low status read
DFCmdSize:=1;
WriteDFCmd;
ReadDFData;
DF_CS:=1;
DFStatus:=DFData;
end;
// DFState
// 0 idle
// 1 blockerase
//
//
//
Procedure InitDataFlash;
var u:byte;
begin
DF_Sck:=0; // passive low clock
nop;
DF_CS:=0;
nop;
DF_WP:=0;
DF_Reset:=0;
for u:=1 to 10 do nop; endfor;
DF_CS:=1;
DFBuffer:=0;
DFBufferIndex:=0;
DFState:=0; //idle
DF_Reset:=1; // end of reset - operate normally
nop;
ReadDFStatus;
if ((DFStatus and $BC)=$AC) then FlashSize:=512; endif; // blocks @4224bytes
DFBufferSelect:=0;
end;
// block erase opcode 0x50
//procedure ClearDataFlash_;
//var sdata,cnt:byte;
//begin
// DF_Sck:=0;
// DF_CS:=1;
// DF_WP:=1;
// for DFBlock:=0 to 511 do // 512 blocks @ 12ms
// sdata:=$50;
// DF_CS:=0;
// for cnt:=0 to 7 do
// if ((sdata and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
// DF_Sck:=1; // pulse high
// sdata:=sdata shl 1;
// DF_Sck:=0; // default = low
// endfor;
// sdata:=byte(DFBlock shr 3) and $7F;
// for cnt:=0 to 7 do
// if ((sdata and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
// DF_Sck:=1; // pulse high
// sdata:=sdata shl 1;
// DF_Sck:=0; // default = low
// endfor;
// sdata:=byte(DFBlock shl 5) and $E0;
// for cnt:=0 to 7 do
// if ((sdata and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
// DF_Sck:=1; // pulse high
// sdata:=sdata shl 1;
// DF_Sck:=0; // default = low
// endfor;
// sdata:=0;
// for cnt:=0 to 7 do
// if ((sdata and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
// DF_Sck:=1; // pulse high
// sdata:=sdata shl 1;
// DF_Sck:=0; // default = low
// endfor;
// DF_CS:=1;
// endfor;
//end;
// DFBufferIndex:word; // into the buffer
// DFReadBuffer:DFBufferT;
// DFWriteBuffer:DFBufferT;
// DFWBCount:byte;
// write from DFWBCount bytes from DFWriteBuffer to the device
//procedure WriteToFlashBuffer;
//var u,cnt,sdata:byte;
//begin
// if DFBufferSelect=0 then DFCmdBuffer[1]:=$84; else DFCmdBuffer[1]:=$87; endif;
// DFCmdBuffer[2]:=0;
// DFCmdBuffer[3]:=hi(DFBufferIndex);
// DFCmdBuffer[4]:=lo(DFBufferIndex);
// WriteDFCmd;
// for u:=0 to DFWBCount-1 do
// sdata:=DFWriteBuffer[u];
// for cnt:=0 to 7 do
// if ((sdata and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
// DF_Sck:=1; // pulse high
// sdata:=sdata shl 1;
// DF_Sck:=0; // default = low
// endfor; // 8 bita
// endfor; // # bytes
// DF_CS:=1;
// DFBufferIndex:=DFBufferIndex+word(DFWBCount);
//end;
// moves buffer X to page "DFPage"
//procedure BuffertoFlash;
//begin
// if DFBufferSelect=0 then DFCmdBuffer[1]:=$83; else DFCmdBuffer[1]:=$86; endif;
// tw:=DFPage;
// tw:=tw shl 2;
// DFCmdBuffer[2]:=twb2;
// DFCmdBuffer[3]:=twb1;
// DFCmdBuffer[4]:=0;
// WriteDFCmd;
//end;
Procedure FlashReset;
var u:byte;
begin
//debugpulse;
DF_CS:=1;
DF_Sck:=0; //SPIMode0
DF_CS:=0;
nop;
DF_Reset:=0;
for u:=1 to 4 do nop; endfor;
DF_CS:=1;
nop;
DF_Reset:=0;
nop;
end;
//FlashWritePtr:=5; //index into RxBuffer
//FlashWriteLen:=RxBuffer[1]-7;
procedure FlashWriteProc;
var cnt,h,u:byte;
begin
//debugpulse;
DF_Sck:=0; //SPIMode0
DF_CS:=1;
DF_WP:=1;
DF_CS:=0;
cnt:=0;
while (FlashWriteLen > cnt) do
h:=RxBuf[FlashWritePtr];
for u:=1 to 8 do
if ((h and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
DF_Sck:=1; // pulse high
h:=h shl 1;
DF_Sck:=0; // default = low
endfor;
inc(FlashWritePtr);
inc(cnt);
endwhile;
DF_CS:=1;
end;
// FlashReadLen = #of bytes to read <= Flashbuffer
//FlashWritePtr:=6; //index into RxBuffer
//FlashWriteLen:=RxBuffer[1]-8;
procedure FlashReadProc;
var cnt,h,u:byte;
begin
//debugpulse;
DF_Sck:=0; //SPIMode0
DF_CS:=1;
DF_WP:=1;
DF_CS:=0;
cnt:=0;
while (FlashWriteLen > cnt) do
h:=RxBuf[FlashWritePtr];
for u:=1 to 8 do
if ((h and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
DF_Sck:=1; // pulse high
h:=h shl 1;
DF_Sck:=0; // default = low
endfor;
inc(FlashWritePtr);
inc(cnt);
endwhile;
FlashReadPtr:=0; // pointing into DFReadBuffer
cnt:=0;
while (cnt < FlashReadLen) do
h:=0;
for u:=1 to 8 do
DF_Sck:=1; // pulse high
DF_Sck:=0; // default = low
h:=h shl 1;
nop;
if (DF_SO=true) then
h:=h or $01;
//debugpulse;
endif;
endfor;
DFReadBuffer[cnt]:=h;
inc(cnt);
endwhile;
DF_CS:=1;
end;
// data is in DFWriteBuffer, length is DFWriteLen
Procedure ShiftWritebuffer;
var cnt,h,u,n:byte;
begin
DF_Sck:=0; //SPIMode0
DF_CS:=1;
DF_WP:=1;
DF_CS:=0;
cnt:=0;
u:=DFWriteLen;
while (u > cnt) do
h:=DFWriteBuffer[cnt];
for n:=1 to 8 do
if ((h and $80)=$80) then DF_SI:=1; else DF_SI:=0; endif;
DF_Sck:=1; // pulse high
h:=h shl 1;
DF_Sck:=0; // default = low
endfor;
inc(cnt);
endwhile;
DF_CS:=1;
end;
// RTCSec:byte;
// RTCMin:byte;
// RTCHour:byte;
// RTCDate:byte;
// RTCMonth:byte;
// RTCDay:byte;
// RTCYear:byte;
// DFWriteBuffer
procedure WriteRTCDataToBuffer(Code:byte); // $AA : startup, $AB : timed, $AC : modechange, $AD: RTC Timed Log start/stop
var w:word;
begin
if (DFBufferSelect=0) then
DFWriteBuffer[0]:=$84; // wtite to buffer1
else
DFWriteBuffer[0]:=$87; // wtite to buffer2
endif;
DFWriteBuffer[1]:=0;
DFWriteBuffer[2]:=hi(DFBufferIndex);
DFWriteBuffer[3]:=lo(DFBufferIndex);
DFWriteBuffer[4]:=$55;
DFWriteBuffer[5]:=Code;
DFWriteBuffer[6]:=RTCYear;
DFWriteBuffer[7]:=RTCMonth;
DFWriteBuffer[8]:=RTCDay;
DFWriteBuffer[9]:=RTCDate;
DFWriteBuffer[10]:=RTCHour;
DFWriteBuffer[11]:=RTCMin;
DFWriteBuffer[12]:=RTCSec;
DFWriteBuffer[13]:=$55;
DFWriteBuffer[14]:=$AA;
DFWriteLen:=15;
ShiftWritebuffer;
DFBufferIndex:=DFBufferIndex+11;
if (DFBufferIndex>512) then // copy buffer
if (DFBufferSelect=0) then
DFWriteBuffer[0]:=$83; // write buffer1
DFBufferSelect:=1;
else
DFWriteBuffer[0]:=$86; // write buffer2
DFBufferSelect:=0;
endif;
w:=DFPage shl 2;
DFWriteBuffer[1]:=hi(w);
DFWriteBuffer[2]:=lo(w);
DFWriteBuffer[3]:=0;
DFWriteLen:=4;
ShiftWritebuffer;
inc(DFPage);
if (DFPage>4095) then
Mode:=mode and $7F; // clear logging
endif;
DFBufferIndex:=0;
WriteFlashIndexToRAM;
else
WriteFlashIndexToRAM;
endif;
end;
// Channel1:LongWord;
// Channel2:LongWord;
// Channel3:LongWord;
// DFWriteBuffer
procedure WriteADCDataToBuffer;
var w:word;
begin
if (DFBufferSelect=0) then
DFWriteBuffer[0]:=$84; // wtite to buffer1
else
DFWriteBuffer[0]:=$87; // wtite to buffer2
endif;
DFWriteBuffer[1]:=0;
DFWriteBuffer[2]:=hi(DFBufferIndex);
DFWriteBuffer[3]:=lo(DFBufferIndex);
CopyBlock(@Channel1,@DFWriteBuffer+4,12); // 3 times 4 bytes
DFWriteLen:=16;
ShiftWritebuffer;
DFBufferIndex:=DFBufferIndex+12;
if (DFBufferIndex>512) then // copy buffer
if (DFBufferSelect=0) then
DFWriteBuffer[0]:=$83; // write buffer1
DFBufferSelect:=1;
else
DFWriteBuffer[0]:=$86; // write buffer2
DFBufferSelect:=0;
endif;
w:=DFPage shl 2;
DFWriteBuffer[1]:=hi(w);
DFWriteBuffer[2]:=lo(w);
DFWriteBuffer[3]:=0;
DFWriteLen:=4;
ShiftWritebuffer;
inc(DFPage);
if (DFPage>4095) then
Mode:=mode and $7F; // clear logging
endif;
DFBufferIndex:=0;
WriteFlashIndexToRAM;
else
WriteFlashIndexToRAM;
endif;
end;
procedure WriteTempDatatoBuffer(Code:byte); // code for timer is $AE
var w:word;
begin
if (DFBufferSelect=0) then
DFWriteBuffer[0]:=$84; // wtite to buffer1
else
DFWriteBuffer[0]:=$87; // wtite to buffer2
endif;
DFWriteBuffer[1]:=0;
DFWriteBuffer[2]:=hi(DFBufferIndex);
DFWriteBuffer[3]:=lo(DFBufferIndex);
DFWriteBuffer[4]:=$55;
DFWriteBuffer[5]:=Code;
DFWriteBuffer[6]:=lo(ADC0);
DFWriteBuffer[7]:=hi(ADC0);
DFWriteBuffer[8]:=$55;
DFWriteBuffer[9]:=$AA;
DFWriteLen:=10;
ShiftWritebuffer;
DFBufferIndex:=DFBufferIndex+6;
if (DFBufferIndex>512) then // copy buffer
if (DFBufferSelect=0) then
DFWriteBuffer[0]:=$83; // write buffer1
DFBufferSelect:=1;
else
DFWriteBuffer[0]:=$86; // write buffer2
DFBufferSelect:=0;
endif;
w:=DFPage shl 2;
DFWriteBuffer[1]:=hi(w);
DFWriteBuffer[2]:=lo(w);
DFWriteBuffer[3]:=0;
DFWriteLen:=4;
ShiftWritebuffer;
inc(DFPage);
if (DFPage>4095) then
Mode:=mode and $7F; // clear logging
endif;
DFBufferIndex:=0;
WriteFlashIndexToRAM;
else
WriteFlashIndexToRAM;
endif;
end;
procedure ClearDataFlash;
var block:word;
w:word;
begin
for block:=0 to 511 do
DFCmdBuffer[1]:=$50;
w:=block shl 5;
DFCmdBuffer[2]:=hi(block);
DFCmdBuffer[3]:=lo(block);
DFCmdBuffer[4]:=0;
DFWriteLen:=4;
ShiftWritebuffer;
// wait for complete
nop;
While DF_RDY=false do nop; endwhile; // blocking loop
endfor;
DFPage:=0;
DFBufferIndex:=0;
WriteFlashIndexToRAM;
end;
// when the looging terminates,
// write the partial buffer
procedure FlushBuffertoFlash;
var w:word;
begin
if (DFBufferIndex<>0)then
if (DFBufferSelect=0) then
DFWriteBuffer[0]:=$83; // write buffer1
DFBufferSelect:=1;
else
DFWriteBuffer[0]:=$86; // write buffer2
DFBufferSelect:=0;
endif;
w:=DFPage shl 2;
DFWriteBuffer[1]:=hi(w);
DFWriteBuffer[2]:=lo(w);
DFWriteBuffer[3]:=0;
DFWriteLen:=4;
ShiftWritebuffer;
inc(DFPage);
DFBufferIndex:=0;
WriteFlashIndexToRAM;
endif; //bufferindex <>0
end;
procedute initvars;
begin
..
ClearFlashFlag:=0;
InitDataFlash;
..
end;
Questions ?
Suggestions?
Feedback ?
sponsored links
embedded
home
last updated : 24.oct.06, or perhaps later
Copyright (99,2006) Ing.Büro R.Tschaggelar