|
|
View previous topic :: View next topic |
Author |
Message |
chrmjenkins
Joined: 06 Mar 2008 Posts: 4
|
18f452 interface with spi flash device |
Posted: Thu Mar 06, 2008 5:05 pm |
|
|
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
|
|
Posted: Thu Mar 06, 2008 5:41 pm |
|
|
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
|
|
Posted: Wed Mar 26, 2008 8:38 am |
|
|
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
|
|
Posted: Mon Apr 28, 2008 9:36 am |
|
|
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
|
|
Posted: Mon Apr 28, 2008 11:00 am |
|
|
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
|
|
Posted: Mon Apr 28, 2008 5:47 pm |
|
|
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
|
|
Posted: Mon Apr 28, 2008 6:39 pm |
|
|
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
|
|
Posted: Mon Apr 28, 2008 7:37 pm |
|
|
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
|
|
Posted: Tue Apr 29, 2008 5:35 am |
|
|
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? |
|
|
|
|
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
|