View previous topic :: View next topic |
Author |
Message |
artohautala
Joined: 17 Nov 2011 Posts: 187
|
spi flash_WRITE writes 3 bytes instead of one? |
Posted: Tue Jan 17, 2012 11:36 am |
|
|
Hello everybody,
Please help to solve my problem...
I'm trying to write one byte to 128 Mb flash memory M25P128
but when I write one byte it writes 3 bytes:
For instance: address 0xEC0000 (first address in sector 59)
and data is D170
When I read data:
0xEC0000 is D170 OK
0xEC000001 is D05 WHY?
0xEC0002 is D0 WHY
0xEX0003 is 0xFF ok
and data after this in all addresses is 0xFF as expected...
Thank you for good discussion forum
Here is part of my code:
Code: |
These are before main() sure:
#define flash_WREN 0x06 //flash muistin write enable
#define PAGE_prog 0x02 //flash muistin page program enable
#define flash_RSTATUS 0x05 //flash muistin READ status osoite
#define flash_READ 0x03 //flash muistin READ enable
#define SEC_erase 0xD8 //flash muistin SECTOR ERASE
#define FULL_erase 0xC7 //flash muistin BULK ERASE
//***********************************************************************************************
short int flash_WRITE(int8 flash_data)
{
int8 read_data,timeout;
output_high(flash_sel);delay_us(2);
spi_write(flash_WREN);delay_us(2);
output_low(flash_sel);
delay_us(2);
output_high(flash_sel); delay_us(2);
spi_write(PAGE_prog); delay_us(2);
send_FLASH_address(); delay_us(2);
spi_write(flash_data);delay_us(2);
output_low(flash_sel);
timeout = 0;
while(flash_busy()& (timeout < 255))
{
delay_us(500);
++timeout;
if(timeout == 255)
{
clear_row(14);clearTextBuffer();
strcpy(teksti,"flash write (timeout) error"); text_xy(0,14);text(teksti);
delay_ms(3000);
return FALSE;
}
}
delay_ms(20);
read_data = READ_flash();
if(read_data == flash_data)
{
return TRUE;
}
else
{
clear_row(14);clearTextBuffer();
strcpy(teksti,"flash compare error"); text_xy(0,14);text(teksti);
delay_ms(3000);
return FALSE;
}
}
//***********************************************************************************************
short int flash_busy(void)
{
int8 status;
short int bitti_testi;
output_high(flash_sel);delay_us(2);
spi_write(flash_RSTATUS);delay_us(2);
status = spi_read(0);
output_low(flash_sel);
bitti_testi = bit_test(status,0);
return bitti_testi;
}
//***********************************************************************************************
void send_FLASH_address(void) //läh. globaalin flash_addr osoitteen 24 bits SPI-väylään
{
int8 msb,mmsb,lsb;
msb =(flash_addr >> 16);
mmsb = flash_addr >> 8;
lsb= flash_addr;
spi_write(msb); delay_us(2); //MSB first
spi_write(mmsb);delay_us(2);
spi_write(lsb);delay_us(2);
}
//***********************************************************************************************
:) :) |
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Jan 17, 2012 1:39 pm |
|
|
a lot of code is missing here
- starting with the HOW you handle SPI setup / initialization.
also i am not seeing code on HOW you got the read back data you complain about. the code for the read_flash() function leaps to mind .......
more code needs to be known - before i could begin to comment on a possible fault with the "COMMENT FREE" driver code you have here. |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Tue Jan 17, 2012 2:13 pm |
|
|
asmboy wrote: | a lot of code is missing here
- starting with the HOW you handle SPI setup / initialization.
also i am not seeing code on HOW you got the read back data you complain about. the code for the read_flash() function leaps to mind .......
more code needs to be known - before i could begin to comment on a possible fault with the "COMMENT FREE" driver code you have here. |
Ok thanks for your answer ...
here is my spi setup:
setup_spi(spi_master|spi_mode_0|spi_clk_div_64 );
and here is my code to read memory:
Code: |
//***********************************************************************************************
int8 READ_flash(void)
{
int8 read_data;
output_high(flash_sel); delay_us(2); //flash muisti ON
spi_write(flash_READ); //flash READ ON
send_FLASH_address(); //lähetetään osoite
read_data = spi_read(0); //luetaan data
output_low(flash_sel); //flash muisti OFF
return read_data;
}
//*********************************************************************************************** |
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Jan 17, 2012 5:18 pm |
|
|
what PIC ?
what #FUSES
what compiler version ?
a solution will come down to knowing what PIC pins are doing what for the pic control of the EEPROM CHIP enable and SPI control ( as hardware SPI is all that works with the spi_ functions you selected )
and then diagnosing what is wrong the way you try to communicate with it.
ie: whats wrong with this stab at a driver for the Serial EEPROM in question
each bit of extra info you post helps
don't be stingy ...
BTW have you read this ???
http://www.ccsinfo.com/forum/viewtopic.php?t=44460&highlight=m25p128
|
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Tue Jan 17, 2012 11:00 pm |
|
|
asmboy wrote: | what PIC ?
what #FUSES
what compiler version ?
a solution will come down to knowing what PIC pins are doing what for the pic control of the EEPROM CHIP enable and SPI control ( as hardware SPI is all that works with the spi_ functions you selected )
and then diagnosing what is wrong the way you try to communicate with it.
ie: whats wrong with this stab at a driver for the Serial EEPROM in question
each bit of extra info you post helps
don't be stingy ...
BTW have you read this ???
http://www.ccsinfo.com/forum/viewtopic.php?t=44460&highlight=m25p128
|
Yes my compiler version is 4.018 and I'm using pic18f452.
This is first line in main():
Code: |
setup_spi(spi_master|spi_mode_0|spi_clk_div_64 ); //mode 0 tai 3 |
Here are fuses:
Code: |
#include<18F452.h>
#include <string.h>
#use delay(clock = 20000000,restart_wdt)
#fuses HS,NOWDT,NOPROTECT //oltava HS !
#zero_ram //nollaa kaikki muuttujat alussa
|
Here are defines:
Code: |
#include <graph_rutines.c>
#define RTC_SDA PIN_C1 //reaalikellon datalinja
#define RTC_SCL PIN_C0 //reaalikellon kellopulssi
#define MENU PIN_A0 //ylempi näppäin, normally closed, tila on FALSE
#define SET PIN_A1 //alempi näppäin, normally closed, tila on FALSE
#use i2c(master, sda=RTC_SDA, scl=RTC_SCL, RESTART_WDT)
#define flash_SEL PIN_C2 //flash-muistin chip select, testattu OK
#define flash_SCL PIN_C3 //flash-muistin kellolinja, testattu OK
#define flash_MISO PIN_C4 //flash-muistin serial out MISO (master in slave out)TEST OK
#define flash_MOSI PIN_C5 //flash-muistin serial in MOSI (master out slave in)TEST OK
#define flash_WREN 0x06 //flash muistin write enable
#define PAGE_prog 0x02 //flash muistin page program enable
#define flash_RSTATUS 0x05 //flash muistin READ status osoite
#define flash_READ 0x03 //flash muistin READ enable
#define SEC_erase 0xD8 //flash muistin SECTOR ERASE
#define FULL_erase 0xC7 //flash muistin BULK ERASE
#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)
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Jan 18, 2012 6:45 am |
|
|
Let's see...
PIC18F452 is a 5 volt device
M25P128 is a 3 volt device
Do you have a proper logic level translation chip between these parts ?
Before you can debug the software, you have to be sure the hardware is correct. |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Wed Jan 18, 2012 7:12 am |
|
|
temtronic wrote: | Let's see...
PIC18F452 is a 5 volt device
M25P128 is a 3 volt device
Do you have a proper logic level translation chip between these parts ?
Before you can debug the software, you have to be sure the hardware is correct. |
Thanks for your answer temtronic.
Yes I have logic converters.
I'm rather sure my hardware is ok because sector erase and bulk erase works. I can't program bits back to one's before I sector erase or bulk erase, and after erase I can write again. But problem is that first byte is in right address and it's ok but two following bytes are programmed also so I write 3 data bytes instead of one.
One thing I'm not sure if my logic converter rise and fall times are ok
datasheet of memory says min. 0.1 V /ns and it is rather fast.
Ok. This is link to my level converter schematic:
http://tinyurl.com/7ft6fvh
and this link is schematic:
http://tinyurl.com/76fo9rx
best regards |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Wed Jan 18, 2012 8:19 am |
|
|
artohautala wrote: | temtronic wrote: | Let's see...
PIC18F452 is a 5 volt device
M25P128 is a 3 volt device
Do you have a proper logic level translation chip between these parts ?
Before you can debug the software, you have to be sure the hardware is correct. |
Thanks for your answer temtronic.
Yes I have logic converters.
I'm rather sure my hardware is ok because sector erase and bulk erase works. I can't program bits back to one's before I sector erase or bulk erase, and after erase I can write again. But problem is that first byte is in right address and it's ok but two following bytes are programmed also so I write 3 data bytes instead of one.
One thing I'm not sure if my logic converter rise and fall times are ok
datasheet of memory says min. 0.1 V /ns and it is rather fast.
Ok. This is link to my level converter schematic:
http://tinyurl.com/7ft6fvh
and this link is schematic:
http://tinyurl.com/76fo9rx
best regards |
by the way ... same results also using x_fer function and this #use...:
#use spi(FORCE_HW,SAMPLE_RISE, BITS=8, stream=SPI_STREAM) |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Jan 18, 2012 8:34 am |
|
|
Think carefully about what is happening. You are trying to write one byte, it is actually writing more than one. What are the extra bytes? They are 05 00. What does that look like? It looks like a what you send in flash_busy()! So, it is interpreting the flash_busy status request as data to be written. The question is why?
Why indeed... well, if you look at your level convertor you have an open collector driver for the select. That produces a fast high to low transition at its output, but a slower low to high as the capacitance of the select pin (which we don't know: the data sheet doesn't tell us) has to be charged through your 1k5 pull-up resistor. So, we don't know what the low-high rise time is. What we do know is that you give just 2us after the write command before sending the flash_busy request. I'll bet what's happening is that its not rising in time and so the memory IC is thinking the flash_busy request is more data, which is writes. So, either use an active drive or wait longer after the write before asking for data. There's no point in asking for the first write status for a few ms anyway, as its going to take a long time to actually write. You want to ask first in the "maybe it has, maybe it hasn't" region, not as you are at the moment in the "No way, I've barely start to write yet!" region.
Most of your delay_us(2) are pointless any way. You only really need to do anything immediately after activating the select and immediately after deactivating it, to give time for it to rise. Get your oscilloscope out to check how long that really needs to be. You certainly don't need to wait between bytes. |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Wed Jan 18, 2012 9:17 am |
|
|
RF_Developer wrote: | Think carefully about what is happening. You are trying to write one byte, it is actually writing more than one. What are the extra bytes? They are 05 00. What does that look like? It looks like a what you send in flash_busy()! So, it is interpreting the flash_busy status request as data to be written. The question is why?
Why indeed... well, if you look at your level convertor you have an open collector driver for the select. That produces a fast high to low transition at its output, but a slower low to high as the capacitance of the select pin (which we don't know: the data sheet doesn't tell us) has to be charged through your 1k5 pull-up resistor. So, we don't know what the low-high rise time is. What we do know is that you give just 2us after the write command before sending the flash_busy request. I'll bet what's happening is that its not rising in time and so the memory IC is thinking the flash_busy request is more data, which is writes. So, either use an active drive or wait longer after the write before asking for data. There's no point in asking for the first write status for a few ms anyway, as its going to take a long time to actually write. You want to ask first in the "maybe it has, maybe it hasn't" region, not as you are at the moment in the "No way, I've barely start to write yet!" region.
Most of your delay_us(2) are pointless any way. You only really need to do anything immediately after activating the select and immediately after deactivating it, to give time for it to rise. Get your oscilloscope out to check how long that really needs to be. You certainly don't need to wait between bytes. |
YES, that makes sense!
Now I think it works I tested it rapidly...
Thank you so much for your help
I added 200us delay to the beginning of flash_busy function like this:
Code: |
short int flash_busy(void) //testaa onko flash-muisti valmis TRUE jos ei valmis!
{
int8 status;
short int bitti_testi;
delay_us(200); //RECENTLY ADDED DELAY!
output_high(flash_sel); //flash muisti ON
spi_xfer(SPI_STREAM, flash_RSTATUS,8);
status = spi_xfer(SPI_STREAM, 0,8);
output_low(flash_sel); //flash muisti OFF
bitti_testi = bit_test(status,0); //write in progress WIP bit jos valmis se on LOW
return bitti_testi;
}
:) |
|
|
|
|