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