CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

18f452 interface with spi flash device

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
chrmjenkins



Joined: 06 Mar 2008
Posts: 4

View user's profile Send private message

18f452 interface with spi flash device
PostPosted: Thu Mar 06, 2008 5:05 pm     Reply with quote

Ok, I've been writing code to interface a 18f452 through the SPI interface with flash memory. No matter what I do with my code (I've commented it all but a simple debug routine to clock an output), the device does the same thing, begins sinking about 7 mA of current and ramps down to 0 current in about 10 seconds. I can never observe any data output. I've successfully programmed many before so I know I have my crystal and other things set up properly. Can someone see a blatant error in this code? Note: everything in the main is commented out except the include flash.h directive and the debug loop.

Thanks

Code:



#include "flash.h"


#define CS PIN_D3


// SPI configuration value
#define SPI_Config   0x00      // SPI configuration register value   sspcon1
#define SPI_Enable    0x32      // SPI enable    00110010             sspstat1
//#define SPI_Enbuf   0x0001      // Enable the enhanced buffer mode

// AT45DB161B Flash command
#define Array_Read   0xE8      // Continuous array read SPI mode 3
#define Status_Read 0xD7      // Flash status register read SPI mode 3
#define Buf1_Write  0x84      // Flash buffer 1 write
#define Buf2_Write  0x87      // flash buffer 2 write
#define Buf1_Prog   0x83      // Buffer 1 to main memory program with built-in erase
#define Buf2_Prog   0x86      // Buffer 2 to main memory program with built-in erase
#define Mmw_Buf1    0x82      // Memory program via buffer 1
#define Mmw_buf2    0x85      // Memory program via buffer 2

*/
void main(void)
{
   while(1){
   output_high(PIN_C0);
   delay_cycles(320);
   output_low(PIN_C0);
   delay_cycles(320);
   }
/* int i=0;
   int k=0;
   int data =0;
   int page_cnt = 4095;
   int word_cnt = 528;
   int ppc = 0;
   int page_addr = 1;
   int word_addr = 0;
   int buf1_cycle = 1;
   int pass = 1;

   setup_spi( SPI_MASTER | SPI_H_TO_L  |SPI_CLK_DIV_64);
   InitSPI_Flash();      // initialize spi for flash access

   output_high(DBG);

   // write data to flash
   for (i=0; i<10; i++)
   {
      for (k=0; k<529; k++)
      {
         Write_Word(page_addr, word_addr, k, buf1_cycle);
      }
   }

   // write ppc
   Write_PPC(page_addr-1);


   // end of data writing operations

   // start data reading operations

   // Read PPC
   ppc = Read_PPC();

   // Read back data and check data
   page_addr = 1;
   word_addr = 0;

   Init_Read(page_addr, word_addr);
   while(page_addr <= ppc)
   {
      data = writeSPI1(0);

      if (data!=i)
          pass = 0;

      if (i==528)            // reading the current page is complete
      {
         i=0;
         page_addr++;
      }
      else
      {
         i++;
      }
   }

   output_high(DBG);
   // according to pass value, light different LED
   */
}

/*
void InitSPI_Flash(void)
{
   // Init the SPI interface
   // TCSEE = 0;               // Make the pin output pin
   // CSEE = 1;               // De-select Flash
   output_high(CS);           // De-select Flash
   // SetCSSWSPI();             // De-select Flash
   // SSPCON1 = SPI_Config;      // load config bits into SPI CON1 register   // right name?!
   // SSPSTAT = SPI_Enable;      // enable SPI                            // right name?!
   // SPI1CON2 = SPI_Enbuf;      // enable the enhanced buf mode
   // settings now established in test.c
}


// Note CSEE need to be pulled low before executing this function
int writeSPI1( int data )
{
   int return_data;
   // send one byte of data and receive one back at the same time
   //SSPBUF = data;            // write to buffer to TX
   //while(!(SSPSTAT && 0x01));
   // while(!SPI1STATbits.SPIRBF); // wait for transfer to complete
   return_data = spi_read(data); // This will clock out data and wait for data
                                 // to return, stored in return_data
   return (return_data);
}


void check_status(void)
{
   int word1;
   // read Flash status register and check if it is busy
   // if  it is busy, continuously read status register until it is not busy
   output_low(CS);
   word1 = Status_Read<<8;
   output_high(CS);
   while( !(writeSPI1(word1 & 0x0080)));    // wiat for flash ready
   output_high(CS);
}


int Read_PPC(void)
{
   // Read the PPC value
   int ppc;
   int page_addr = 0x0001;      // Page 1
   int word_addr = 0x0000;      // The first word in page 1

    check_status();            // wait for flash ready

    // ClearSCSWSPI();              // Select the Flash
    output_low(CS);
    Init_Read(page_addr, word_addr);
    ppc = writeSPI1(0);         // read the PPC value
    // SetCSSWSPI();               // de-select Flash
    output_high(CS);
    return ppc;
}


void Write_PPC(int page_cnt)
{
   // write ppc value into flash
   int page_addr, word_addr, word1, word2;

   page_addr = 0x0001;
   word_addr = 0x0000;
   word1 = (Mmw_Buf1<<8) + (page_addr & 0x3FC0);
   word2 = ((page_addr & 0x003F)<<10) + (word_addr & 0x03FF);

    check_status();          // check if Flash is busy

    //ClearSCSWSPI();
    output_low(CS);
    writeSPI1((word1 & 0xFF00)>>8);
    writeSPI1(word1 & 0x00FF);
    writeSPI1((word2 & 0xFF00)>>8);
    writeSPI1(word2 & 0x00FF);
    writeSPI1((page_cnt & 0xFF00)>>8);
    writeSPI1(page_cnt & 0x00FF);
    output_high(CS);
    //SetCSSWSPI();
}


// Note CSEE need to be pulled low before executing this function
void Init_Read(int page_addr, int word_addr)
{
   // send the continuous array command to Flash
   int word1, word2;
   word1 = (Array_Read<<8) + (page_addr & 0x3FC0);
   word2 = (page_addr<<10) + (word_addr & 0x03FF);

   //ClearSCSWSPI();               // select flash
   output_low(CS);
   writeSPI1((word1 & 0xFF00)>>8);         // send read command and address
   writeSPI1(word1 & 0x00FF);
   writeSPI1((word2 & 0xFF00)>>8);
   writeSPI1(word2 & 0x00FF);
   writeSPI1(0x00);            // write 32 don't care bits
   writeSPI1(0x00);
   writeSPI1(0x00);
   writeSPI1(0x00);
   output_high(CS);
   //SetCSSWSPI();
}


void Init_Write(int buf1_cycle)
{
   //send the buf write command to Flash
   int word1;
   if (buf1_cycle)
     word1 = Buf1_Write<<8;
   else
     word1 = Buf2_Write<<8;

   //ClearSCSWSPI();
   output_low(CS);
   writeSPI1((word1 & 0xFF00)>>8);
   writeSPI1(word1 & 0x00FF);
   writeSPI1(0x00);
   writeSPI1(0x00);
   output_high(CS);
   //SetCSSWSPI();
}


void Page_Prog( int page_addr, int buf1_cycle )
{
   // Send the main memry programming command
   int word1, word2;
   if (buf1_cycle)
     word1 = (Buf1_Prog<<8) + (page_addr & 0x3FC0);
   else
     word1 = (Buf2_Prog<<8) + (page_addr & 0x3FC0);

   word2 = page_addr<<10;

   check_status();

   //ClearSCSWSPI();
   output_low(CS);
   writeSPI1((word1 & 0xFF00)>>8);
   writeSPI1(word1 & 0x00FF);
   writeSPI1((word2 & 0xFF00)>>8);
   writeSPI1(word2 & 0x00FF);
   output_high(CS);
   //SetCSSWSPI();
}


void Write_Word( int page_addr, int word_addr, int data, int buf1_cycle )
{
   // send a word to Flash
  if (page_addr < 4096)         // write only before exceeding flash size
  {
   if (word_addr ==0)          // start a new page
   {
      Init_Write(buf1_cycle);
      output_low(CS);
      writeSPI1((data & 0xFF00)>>8);
      writeSPI1(data & 0x00FF);
      output_high(CS);
   }
   else
   {
      output_low(CS);
      writeSPI1((data & 0xFF00)>>8);      // continuously write in the current page
      writeSPI1(data & 0x00FF);
      output_high(CS);
   }


   if (word_addr == 528)               // The current buffer (page) is full
   {
      //SetCSSWSPI();                     // end the buf write operation
      Page_Prog(page_addr, buf1_cycle);    // write the buf content to main memory

      word_addr = 0;
      page_addr = page_addr + 1;          // move the next page
      buf1_cycle = !buf1_cycle;           // change to the other buffer
   }
   else
   {
      word_addr = word_addr + 1;         // move to the next word location
   }
  }
}
*/


Code:
#include <18F452.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES RC_IO                    //Resistor/Capacitor Osc
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOOSCSEN                 //Oscillator switching is disabled, main oscillator is source
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOCPD                    //No EE protection
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads

#use delay(clock=12000000)
//#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)


/*
** AT45DB161B Flash Access Function Library head file
**
** Author: Haibo Wang
** Last Modified: 1/12/08
*/

/*
// Initialize PIC24F MCU SPI
void InitSPI_Flash(void);


// Note CSEE need to be pulled low before executing this function
// write a word to flash and get a word back
int writeSPI1( int data );


// Check flash status register and wait for it ready
void check_status(void);


// read the page program counter
int Read_PPC(void);


// Write the page program counter
void Write_PPC(int page_cnt);


// Note CSEE need to be pulled low before executing this function
// Send the continuous array read command
void Init_Read(int page_addr, int word_addr);


// send the buf write command to flash
void Init_Write(int buf1_cycle);


// send the main memory program command
void Page_Prog( int page_addr, int buf1_cycle );


// send a word to flash buffer
void Write_Word( int page_addr, int word_addr, int data, int buf1_cycle );
*/
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 06, 2008 5:41 pm     Reply with quote

Quote:
I can never observe any data output. I've successfully
programmed many before so I know I have my crystal and other things
set up properly. Can someone see a blatant error in this code?

Yes.

Quote:

#FUSES RC_IO //Resistor/Capacitor Osc
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)

#use delay(clock=12000000)

You need to use the HS oscillator fuse to run at 12 MHz. The RC_IO
fuse is only for an external resistor and capacitor oscillator circuit.
With a 12 MHz crystal, it will probably not work at all.
Also, you should always use the NOLVP fuse. If not, your PIC will lockup
when the PGM pin goes high.

Quote:

setup_spi( SPI_MASTER | SPI_H_TO_L |SPI_CLK_DIV_64);

Your SPI mode setup is for Mode 2, according to the table below:
Code:
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H) 

But the data sheet for the AT45DB161B says it uses Modes 0 or 3.
You need to change it to use the correct mode. I suggest Mode 0.
http://www.atmel.com/dyn/resources/prod_documents/doc2224.pdf


Quote:

int i=0;
int k=0;
int data =0;
int page_cnt = 4095;
int word_cnt = 528;

for (k=0; k<529; k++)
{

Most of this is incorrect. In CCS, an 'int' is a 8-bit unsigned integer.
This is different from most other compilers. So, you can't load 4095
into page_cnt, etc. You need to change most of these to 'int16'.

There might be other errors, but these are the ones I saw on the first pass.
chrmjenkins



Joined: 06 Mar 2008
Posts: 4

View user's profile Send private message

PostPosted: Wed Mar 26, 2008 8:38 am     Reply with quote

Well, now I've heavily modified the code that I was given to begin with, and it turns out that I think our flash is bad :-/

Anyone with experience with these modules? I'm getting a constant 36 mA current sink out of the device (it's pre-mounted on a board for ease of interface) regardless of inputs, so I've assumed it's dead and more are on the way.
chrmjenkins



Joined: 06 Mar 2008
Posts: 4

View user's profile Send private message

PostPosted: Mon Apr 28, 2008 9:36 am     Reply with quote

I've modified the original code I was given (quite a lot). I know I'm writing to the flash, but I can't see any response that the flash is taking the read. I don't see any data coming out of the flash in the part of the code where I read, and the status register bit 6 always says the last write was successful (but can I even be sure one was attempted?).

Code:
#include "flash.h"

void main(void)
{
   int i=0;
   int16 k=0;
   int16 data =0;
   //int16 page_cnt = 4095;
   //int16 word_cnt = 528;
   //int16 ppc = 0;
   int16 page_addr = 1;
   int16 word_addr = 0;
   int buf1_cycle = 1;
   int pass = 1;

   output_low(PIN_C1);
   output_low(PIN_C2);
   output_low(PIN_D0);
   output_high(PIN_C0); // for code tracing

   // De-select Flash and setup PIC for SPI MODE 3
   output_high(CS);
   // uncomment for Mode 3
   setup_spi( SPI_MASTER | SPI_H_TO_L  | SPI_XMIT_L_TO_H | SPI_CLK_DIV_64);
   // uncomment for Mode 0
   //setup_spi( SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_64);

   delay_ms(20); // Wait for flash chip initialization period

   //debug loop, see if we can see status coming out of flash
   for (k=0; k <= 65534; k++)
     check_status();
   output_high(PIN_D4);

   delay_ms(10000);

   // write data to flash (10 times redundancy)
   for (i=0; i<10; i++)
   {
      output_low(CS);
      check_status();

      for (k=0; k<528; k += 2)
      {
        // k = word_addr and data
        Write_Word(page_addr, k, k, buf1_cycle);
      }
      output_high(CS); // pushes data from buffer to mem
   }
   // bookkeeping, not necessary to current program function
   page_addr += 1;
   buf1_cycle = !buf1_cycle;

   output_high(PIN_C1);

   // write ppc  (is this necessary?)
   //Init_Write_PPC(page_addr-1);

   // end of data writing operations

   // start data reading operations

   // Read PPC

   page_addr = 1;
   word_addr = 0;

   k = 0;

   output_low(CS);
   check_status();

   //ppc = Read_PPC(page_addr, word_addr);
   // Read back data and check data

   output_high(PIN_D1);
   Init_Read(page_addr, word_addr);
   output_high(PIN_D5);
   while(k < 528){
      data = SPI_READ();
      data = data<<8;
      output_high(PIN_D6);
      data += SPI_READ();

      if (data!=k){
          pass = 0;
          k += 2;
          // break;
          }
      else
          k+= 2;
      }
   output_high(PIN_D2);
   output_high(CS);

   output_high(CS);
   output_high(PIN_C2);

   if (pass == 1)
      output_high(PIN_D0);
   // D0 high if memory checks ok
}

void check_status(void)
{
   // read Flash status register and check if it is busy
   // if  it is busy, continuously read status register until it is not busy
   output_low(CS);
   while(!(SPI_READ(Status_Read) & 0x80));    // wait for flash ready
   output_high(CS);
}


int16 Read_PPC(int16 page_addr, int16 word_addr)
{
   // Read the PPC value
    int16 ppc;
    Init_Read(page_addr, word_addr);
    ppc = SPI_READ();         // read the PPC value
    ppc = ppc<<8;
    ppc += SPI_READ();
    return ppc;
}

// This is an all-in-one function that writes to the buffer, erases
// a flash page, and re-programs it. This is for the initial byte.
// Subsequent bytes can be written as normal until CS is pulled high
// A byte count needs to be maintained to not overfill the buffer.
// Format:
// 8 bit buffer select
// 2 reserved bits
// 12 bit page address
// 10 bits for initial buffer byte to write
void Init_Write_PPC(int16 page_addr, int16 begin_byte, int16 data, int buff_sel)
{
    int word1;

    if (buff_sel)
      word1 = Mmw_Buf1;
    else
      word1 = Mmw_Buf2;

    SPI_WRITE(word1);
    SPI_WRITE((page_addr>>10) & 0x3F);
    SPI_WRITE(((page_addr<<2) & 0xFC) | ((begin_byte>>8) & 0x03));
    SPI_WRITE(begin_byte & 0xFF);
    SPI_WRITE((data>>8) & 0xFF);
    SPI_WRITE(data & 0xFF);
    // This is left open for transmission of further bytes until CS pulled high!
}


// Begin a continuous array read
// Format:
// 8 bit continuous read opcode
// 2 reserved bits
// 12 bit page addr
// 10 bit begin byte addr
// 32 don't care bits
void Init_Read(int16 page_addr, int16 word_addr)
{
   // make sure CS is low, and status not busy

   SPI_WRITE(Array_Read);         // send read command and address
   SPI_WRITE((page_addr>>8) & 0x3F);
   SPI_WRITE((page_addr & 0xFC) | ((word_addr>>8) & 0x03));
   SPI_WRITE(word_addr & 0xFF);
   SPI_WRITE(0x00);            // write 32 don't care bits
   SPI_WRITE(0x00);
   SPI_WRITE(0x00);
   SPI_WRITE(0x00);
   // pull CS high when done reading, (can continue read with SPI_READ())
}

// It is responsibility of user to put CS
// back high after use
// Format:
// 8 bit buff command
// 14 don't care bits
// ten address bits
void Init_Write(int16 word_addr, int buf1_cycle)
{
   //send the buf write command to Flash
   int word1;
   if (buf1_cycle)
     word1 = Buf1_Write;
   else
     word1 = Buf2_Write;

   SPI_WRITE(word1);
   SPI_WRITE(0x00);
   SPI_WRITE((word_addr>>8) & 0x03);
   SPI_WRITE(word_addr & 0xFF);
}

// Format for Page_Prog
// 8 bits: buffer select
// followed by two reserved bits, 12 address bits, 10 dc bits
void Page_Prog( int16 page_addr, int buf1_cycle )
{
   // Send the main memry programming command
   int word1;
   if (buf1_cycle)
     word1 = Buf1_Prog;
   else
     word1 = Buf2_Prog;

   // page_addr is 16 bits, but only least significant 12 are meaningful
   SPI_WRITE(word1);
   SPI_WRITE((page_addr>>10) & 0x3F);
   SPI_WRITE((page_addr<<2) & 0xFC);
   SPI_WRITE(0x00);
}

// Currently, this function facilitates the writing of a whole buffer in the
// flash memory. It also writes the buffer to memory.
void Write_Word( int16 page_addr, int16 word_addr, int16 data, int buf1_cycle )
{
   // send a word to Flash
  if (page_addr < 4096)         // write only before exceeding flash size
    {
   if (word_addr ==0)          // start a new page
     {
      Init_Write(word_addr, buf1_cycle);
      SPI_WRITE((data >> 8) & 0xFF);
      SPI_WRITE(data & 0xFF);
     }
   else if (word_addr != 528)
     {
      SPI_WRITE((data >> 8) & 0xFF);      // continuously write in the current page
      SPI_WRITE(data & 0xFF);
     }
   else // (word_addr == 528)  The current buffer (page) is full
     {
     output_high(CS); // signify buffer write done
   
     delay_us(10); // give time to take effect

     output_low(CS); //enable to program page
     check_status();
     Page_Prog(page_addr, buf1_cycle);    // write the buf content to main memory
     //output_high(CS); // initiate page prog, (done outside of function)
     }
   }
}




Code:
#include <18F452.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                    //Resistor/Capacitor Osc
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOOSCSEN                 //Oscillator switching is disabled, main oscillator is source
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV20                   //Brownout reset at 2.0V
#FUSES NOPUT                    //No Power Up Timer
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                      //No Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOCPD                    //No EE protection
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads

#use delay(clock=12000000)
//#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)


/*
** AT45DB161B Flash Access Function Library head file
**
** Author: Haibo Wang
** Last Modified: 1/12/08
*/

#define CS PIN_D3

// SPI configuration value
#define SPI_Config   0x00      // SPI configuration register value   sspcon1
#define SPI_Enable    0x32      // SPI enable    00110010             sspstat1
//#define SPI_Enbuf   0x0001      // Enable the enhanced buffer mode

// AT45DB161B Flash command
#define Array_Read  0xE8      // Continuous array read SPI mode 3
#define Status_Read 0xD7      // Flash status register read SPI mode 3
#define Buf1_Write  0x84      // Flash buffer 1 write
#define Buf2_Write  0x87      // flash buffer 2 write
#define Buf1_Prog   0x83      // Buffer 1 to main memory program with built-in erase
#define Buf2_Prog   0x86      // Buffer 2 to main memory program with built-in erase
#define Mmw_Buf1    0x82      // Memory program via buffer 1
#define Mmw_buf2    0x85      // Memory program via buffer 2


// Check flash status register and wait for it ready
void check_status(void);


// read the page program counter
int16 Read_PPC(int16 page_addr, int16 word_addr);


// Write the page program counter
void Init_Write_PPC(int16 page_addr, int16 begin_byte, int16 data, int buff_sel);


// Note CSEE need to be pulled low before executing this function
// Send the continuous array read command
void Init_Read(int16 page_addr, int16 word_addr);


// send the buf write command to flash
void Init_Write(int16 word_addr, int buf1_cycle);


// send the main memory program command
void Page_Prog( int16 page_addr, int buf1_cycle );


// send a word to flash buffer
void Write_Word( int16 page_addr, int16 word_addr, int16 data, int buf1_cycle );

ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Apr 28, 2008 11:00 am     Reply with quote

You got a nice set of defines for the SPI modes and then you write the setup like:
Code:
   setup_spi( SPI_MASTER | SPI_H_TO_L  | SPI_XMIT_L_TO_H | SPI_CLK_DIV_64);
Don't you think it is easier to read when you write:
Code:
   setup_spi( SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64);
Now the code is self explaining (no need for comments).

Code:
   // write data to flash (10 times redundancy)
I don't understand this. Are you here assuming that writing the same value 10 times will give better performance? Something like a burn-in test?
Beware that Flash memory will degrade a little bit with every page erase (It can be erased several thousand times, but I can't find the number in the datasheet).

Code:
   for (i=0; i<10; i++)
   {
      output_low(CS);
      check_status();
Check_status() also makes the CS line low, you don't have to do it. Worse is that check_status() makes the CS line inactive on exit, this means that the rest of this loop has an in-active chip while it assumes otherwise.


Code:
      for (k=0; k<528; k += 2)
      {
        // k = word_addr and data
        Write_Word(page_addr, k, k, buf1_cycle);
      }
Your word write routines has several flaws:
1) The Flash chip has a page size of 528 bytes, not words.
2) Writing a word to address 527 will wrap the buffer and overwrite address 0.
3) There is undocumented behaviour that writing to address 528 will program the current page (data given as parameter is thrown away). It doesn't look like this is causing problems in your current code, but hidden functionality like this is dangerous. At least add it to the function description.

Code:
      output_high(CS); // pushes data from buffer to mem
The Flash chip will only copy the buffer to flash memory if you start the sequence with the correct opcodes (82h or 85h, depending on buffer number). I can't check this because the code for Init_Write() is missing.

I didn't look at the rest of the code as this takes me too much time. Too many things are wrong with your code.
Try simplifying a lot more! Create test code that writes just a single value to byte 0 at page 0 and try to read this back. Only if this works you add little more functionality and test again. Repeat this process and when it fails you will know the error is in the last step. This development method is the best and fastest method to a stable application.
chrmjenkins



Joined: 06 Mar 2008
Posts: 4

View user's profile Send private message

PostPosted: Mon Apr 28, 2008 5:47 pm     Reply with quote

ckielstra wrote:
You got a nice set of defines for the SPI modes and then you write the setup like:
Code:
   setup_spi( SPI_MASTER | SPI_H_TO_L  | SPI_XMIT_L_TO_H | SPI_CLK_DIV_64);
Don't you think it is easier to read when you write:
Code:
   setup_spi( SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64);
Now the code is self explaining (no need for comments).


I only did that because the documentation was a little unclear. Thanks for clearing it up.

Quote:

Code:
   // write data to flash (10 times redundancy)
I don't understand this. Are you here assuming that writing the same value 10 times will give better performance? Something like a burn-in test?
Beware that Flash memory will degrade a little bit with every page erase (It can be erased several thousand times, but I can't find the number in the datasheet).


The flash memory is cheap and is not an issue. This was more for making the traffic easier to follow on the simple o-scope I have.


Quote:

[
Code:
   for (i=0; i<10; i++)
   {
      output_low(CS);
      check_status();
Check_status() also makes the CS line low, you don't have to do it. Worse is that check_status() makes the CS line inactive on exit, this means that the rest of this loop has an in-active chip while it assumes otherwise.


Code:
      for (k=0; k<528; k += 2)
      {
        // k = word_addr and data
        Write_Word(page_addr, k, k, buf1_cycle);
      }
Your word write routines has several flaws:
1) The Flash chip has a page size of 528 bytes, not words.
2) Writing a word to address 527 will wrap the buffer and overwrite address 0.
3) There is undocumented behaviour that writing to address 528 will program the current page (data given as parameter is thrown away). It doesn't look like this is causing problems in your current code, but hidden functionality like this is dangerous. At least add it to the function description.


The control variable jumps by two each time, not one. In this case, a "word" is two bytes. Thanks for the pointer about the last address.

Quote:

Code:
      output_high(CS); // pushes data from buffer to mem
The Flash chip will only copy the buffer to flash memory if you start the sequence with the correct opcodes (82h or 85h, depending on buffer number). I can't check this because the code for Init_Write() is missing.


Init_write is included in the code posted.

Quote:

I didn't look at the rest of the code as this takes me too much time. Too many things are wrong with your code.
Try simplifying a lot more! Create test code that writes just a single value to byte 0 at page 0 and try to read this back. Only if this works you add little more functionality and test again. Repeat this process and when it fails you will know the error is in the last step. This development method is the best and fastest method to a stable application.


The problem is that this is code ported from code in a book that is supposed to work. I've been operating under the assumption I've converted wrongly (going from 16 bit to 8 bit pic).
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Mon Apr 28, 2008 6:39 pm     Reply with quote

ckielstra writes
Quote:
I didn't look at the rest of the code as this takes me too much time. Too many things are wrong with your code.

Porting code implies that you can lift the code and carry it unaided to its destination. This is very much different than translation. A bilingual [spam] can translate Einstein's ideas from German into English. It works as long as nothing goes wrong. If something does go wrong then a complete understanding of the idea is necessary. The advice of getting the simplest possible thing to work with the flash memory and the PIC is a good one.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Apr 28, 2008 7:37 pm     Reply with quote

chrmjenkins wrote:
ckielstra wrote:
I can't check this because the code for Init_Write() is missing.
Init_write is included in the code posted.
My mistake, I overlooked that one.

Have you changed
Code:
   // write data to flash (10 times redundancy)
   for (i=0; i<10; i++)
   {
      output_low(CS);
      check_status();
to
Code:
   // write data to flash (10 times redundancy)
   for (i=0; i<10; i++)
   {
      check_status();   // check_status will set CS high again
      output_low(CS);




I gave it another try but stopped at the following code:
Code:
void Init_Write_PPC(int16 page_addr, int16 begin_byte, int16 data, int buff_sel)
{
    int word1;
The variable begin_byte is declared as an int16 ( == a word).
Variable word1 is declared as an int ( == a byte).

Name giving like this is a sure way to introduce errors.

I'm willing to help you, but then you have to start with a simple as possible program: write a byte to address 0 and read this back.
adrian



Joined: 08 Sep 2003
Posts: 92
Location: Glasgow, UK

View user's profile Send private message

PostPosted: Tue Apr 29, 2008 5:35 am     Reply with quote

chrmjenkins wrote:
Well, now I've heavily modified the code that I was given to begin with, and it turns out that I think our flash is bad :-/

Anyone with experience with these modules? I'm getting a constant 36 mA current sink out of the device (it's pre-mounted on a board for ease of interface) regardless of inputs, so I've assumed it's dead and more are on the way.


Quite possibly. Upto this point you have not given any details of the physical circuit. What voltage are you powering your devices from? The AT45DB161B has SPI lines that are +5V tolerant, but the device should be powered at +3V3. If you are powering your PIC from +3V3 then a low voltage version would be required. Also are you using the /write protect input?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group