|
|
View previous topic :: View next topic |
Author |
Message |
2pi
Joined: 16 Dec 2005 Posts: 7 Location: vienna/austria
|
SPI Problem with ATMEL AT25F1024A [solved] |
Posted: Fri Dec 16, 2005 6:51 am |
|
|
Hello!
I´m a Microchip/CCS Newbie and I got some problems with the SPI.
I´m using the PIC16F687 @ 8MHZ, 3.6 V and i´ve compilerversion 3.235.
I´m using the spi interface of the chip to connect it with a atmel 25f1024A serial flash.
i´ve connected :
pic <-> flash
c0 ~cs
b4 so
c2 ~wp
c1 ~hold
b6 sck
c7 si
and i´m using the spi_read() and spi_write() routines. Further I initialise the SPI interface with
Code: | setup_spi(SPI_MASTER|SPI_CLK_DIV_16|SPI_L_TO_H); |
my first task was to test the serial number and the manufacturer id. for this i´ve written the following code:
Code: |
output_low(nCS); // pull down CS -> select device
spi_write(READ_MAN_PROD_ID); // write command to SPI
id.adress8[0] = spi_read(0); // get data
id.adress8[1] = spi_read(0); // get data
output_high(nCS); // pull up CS -> de-select device
|
with the defines:
Code: | #define READ_MAN_PROD_ID 0b00010101
#define nCS PIN_C0
|
when i probe the voltage on the pins i see that the sck is working fine. the sda of the pic is also working fine.
my problem is that there comes no response from the flash!
i´ve tried to change the command nibbles (higher/lower) and also to mirror them but there is also no response!
the ~wp and the ~hold pins of the flash are always in high state!
the flash should be ok, ´cause it´s new.
has someone suggestions to solve the problem!
thanks a lot!
ps: i hope i use the correct forum![/list]
Last edited by 2pi on Wed Dec 21, 2005 6:35 am; edited 4 times in total |
|
|
Ttelmah Guest
|
|
Posted: Fri Dec 16, 2005 9:27 am |
|
|
First thing, I am puzzled why you have an exclamation mark after the comment that WP and HOLD are always high. These are inputs to the memory chip, and it is up to you to hold them high. If they were low, it would stop things working.
I'd ask one 'simple' thing before looking further. Are you setting all three pins (WP, HOLD, and CS), high somewhere in your initialisation?. You need to set these high, before starting.
Now according to the data sheet for the chip,and the PIC, the bit pattern needed in the configuration registers at the PIC, is CKP=0, CKE=1, SMP=0. Looking at the values in the .h file for your processor, I have a 'nasty feeling', that the compiler may not be setting these correctly (this is unfortunately, a common problem, where it takes a while for the files for a particular chip to be 'right'). I'd try manually overriding these three bits, and see if it affects things. So add:
Code: |
#byte SSPSTAT=0x94
#byte SSPCON=0x14
#bit CKP=SSPCON.4
#bit CKE=SSPSTAT.6
#bit SMP=SSPSTAT.7
setup_spi(SPI_MASTER|SPI_CLK_DIV_16|SPI_L_TO_H);
CKP=SMP=0;
CKE=1;
|
and see if things change.
Best Wishes |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Fri Dec 16, 2005 10:03 am |
|
|
Do you have a pull up resistor on SDI input to the PIC? _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Ttelmah Guest
|
|
Posted: Fri Dec 16, 2005 10:17 am |
|
|
He shouldn't need one. This is SPI, not I2C. The pin can drive to within 0.2v of Vdd, with a 100uA load.
Best Wishes |
|
|
2pi
Joined: 16 Dec 2005 Posts: 7 Location: vienna/austria
|
Thank you for the fast response! |
Posted: Fri Dec 16, 2005 11:55 am |
|
|
@Ttelmah: yeah ~wp and ~hold are booth driven high from the pic. i forgot this code-snippet to copy&paste. that works fine!
to the problem: the serial clock and the serial data out of the pic seem to work. i see the right curves (8 clock cycles and the right data) on the oscilloscope! but there is no answer from the flash (and i checked the connections between the pic and the flash several times, they should be ok, and i also changed the flash (booth flashes are new!)!)
@asmallri: i think that i don't need a pull up, but iĺl try it!
i will try your suggestions on monday, cause i'm sitting in old europe and weekend has started!
i'll inform you with my proceedings(and also drawbacks). |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Fri Dec 16, 2005 7:46 pm |
|
|
Ttelmah wrote: | He shouldn't need one. This is SPI, not I2C. The pin can drive to within 0.2v of Vdd, with a 100uA load.
Best Wishes |
Opps your right. I didn't realise this device actively drives the output high. Not all SPI devices do this. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Ttelmah Guest
|
|
Posted: Sat Dec 17, 2005 3:23 am |
|
|
I only 'knew', because I had looked for this in the data sheet, when I was trying to work out what was happening. A case of 'minds thinking alike'.
:-)
It'll be interesting to hear what the actual problem is. My first hypothesis, was that there was some 'initialisation garbage' on one of the lines, and the chip wasn't being 'deselected' during boot, was seeing this, and getting 'hung', but the poster has now said that these lines are being correctly initialised. I'd still be inclined to 'double check' what is being put into the SSP configuration registers, since this seems to be a common source of problems, and it'd only take the data to be changing on the 'wrong' clock edge, for the setup to fail.
Best Wishes |
|
|
2pi
Joined: 16 Dec 2005 Posts: 7 Location: vienna/austria
|
Problem solved |
Posted: Mon Dec 19, 2005 1:45 am |
|
|
back from weekend, i tried your suggestions!
The compiler didn´t set the bits CKP, CKE, SMP in the correct way!
I used your posted code and now everything is doing fine.
Thank you very much!
Greetings
2pi
|
|
|
Ttelmah Guest
|
|
Posted: Mon Dec 19, 2005 3:58 am |
|
|
This (unfortunately), is an area, where CCS seems to fairly often have problems.... Though the internal functions are nice, and make it possible to ignore what bits are actually required for a particular chip, there is a tendency when chips are introduced, for it to take a suprising number of 'releases' in some cases, before the .h files work right.
I'd send a direct report of the problem to CCS, since it is 'customer feedback' that really allows them to get this sort of fault fixed, but this has happened to me 'often enough', that I will always either check with a simulator, or by 'manually overriding', if a problem appears.
The bytes in the .h file, did not appear to be accessing the bits as I expected, hence my 'suspicion', that this might be the problem.
Glad you have it working now.
Best Wishes |
|
|
2pi
Joined: 16 Dec 2005 Posts: 7 Location: vienna/austria
|
still problems ... |
Posted: Tue Dec 20, 2005 7:40 am |
|
|
it was too early to cheer. there are still problems with the SPI.
setting and reading the status register of the e2prom works, but writting and reading data still doesn´t work. sometimes it looks like it works, but most of the time it reads 0x00 or 0xff back from the seeprom
(or other random numbers, but it read always the same number!).
when the voltage on the sdo pin of the eeprom is monitored it looks like a capacitive dischargin after the last 8 clockcycles (these are the clock cycles where the data should be written from the eeprom on the bus). when the data is low (during the last clock cycles, this means 0x00) there is, after the last clockcycle, also a jump to vpp and also this discharging.
i changed the eeproms several times and checked the lines between eeprom and pic.
i use the following function to read:
Code: |
output_low(nCS); // pull down CS -> select device
spi_write(command); // write command to SPI
spi_write(high_adress); // write higher part of read adress
spi_write(middle_adress);
spi_write(low_adress); // write lower part of read adress
low_adress = spi_read(0); // get data
output_high(nCS); // pull up CS -> de-select device
return(low_adress); // return read value
|
and this code to write:
Code: |
output_low(nCS); // pull down CS -> select device
spi_write(SET_WRITE_ENABLE_LATCH);
spi_write(command); // write command to SPI
spi_write(high_adress); // write higher part of read adress
spi_write(middle_adress); // write higher part of read adress
spi_write(low_adress); // write lower part of read adress
spi_write(data); // write data
delay_us(1);
output_high(nCS); // pull up CS -> de-select device
|
in this function there is no difference when the line spi_write(SET_WRITE_ENABLE_LATCH); is in the code or not.
i have no ideas any more, what to do to get this to work...
2pi
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Tue Dec 20, 2005 9:14 am |
|
|
1) Pls tell us what do you get after read the serial number of the manufacturer id (MAN_PROD_ID)
2) You are using the same parameter value for two different operations.
a) To read from the EEPROM you are using:
Quote: |
spi_write(command); // write command to SPI
|
b) To write to the EEPROM you are using:
Quote: |
spi_write(command);
|
Your code doesn't show us the explicit value of the parameter command.
To read Data from the EEPROM must be:
command = 3;
To write Data to the EEPROM must be:
command = 2;
3) In your reading routine:
Code: |
spi_write(low_adress); // write lower part of read adress
low_adress = spi_read(0); // get data
|
You are naming low_adress to a variable whose value is a real Data AND is the same name used as parameter in the function spi_write(low_adress).
Pls re-check your code that is not only quite confusing but also impredictable in it's results.
Humberto |
|
|
2pi
Joined: 16 Dec 2005 Posts: 7 Location: vienna/austria
|
|
Posted: Tue Dec 20, 2005 9:49 am |
|
|
the full code for writting a byte / the Status Register / the WEN bit in the Status Register:
Code: |
// SPI WRITE (ONE BYTE) =====================================
void spi_write_one_byte(unsigned int8 command, unsigned int32 adress, unsigned int8 data) {
unsigned int8 low_adress, high_adress, middle_adress;
low_adress = make8(adress,0);
middle_adress = make8(adress,1);
high_adress = make8(adress,2);
if ((command==RESET_WRITE_ENABLE_LATCH)||(command==SET_WRITE_ENABLE_LATCH)) {
output_low(nCS); // pull down CS -> select device
spi_write(command); // write command to SPI
delay_us(1);
output_high(nCS); // pull up CS -> de-select device
delay_ms(100);
}
// write STATUS REGISTER
else if (command==WRITE_STATUS_REGISTER) {
output_low(nCS); // pull down CS -> select device
spi_write(command); // write command to SPI
spi_write(data); // write data
delay_us(1);
output_high(nCS); // pull up CS -> de-select device
delay_ms(100);
}
// normal write cycle
else {
output_low(nCS); // pull down CS -> select device
spi_write(SET_WRITE_ENABLE_LATCH);
spi_write(command); // write command to SPI
spi_write(high_adress); // write higher part of read adress
spi_write(middle_adress); // write higher part of read adress
spi_write(low_adress); // write lower part of read adress
spi_write(data); // write data
delay_us(1);
output_high(nCS); // pull up CS -> de-select device
}
delay_us(500);
}
|
the full code to read a Byte from the Se2prom:
Code: |
int8 spi_read_one_byte(unsigned int8 command, unsigned int32 adress) {
unsigned int8 low_adress, middle_adress, high_adress;
low_adress = make8(adress,0);
middle_adress = make8(adress,1);
high_adress = make8(adress,2);
// read STATUS REGISTER
if (command==READ_STATUS_REGISTER) {
output_low(nCS); // pull down CS -> select device
spi_write(command); // write command to SPI
low_adress = spi_read(0); // get data
output_high(nCS); // pull up CS -> de-select device
}
// normal read cycle
else {
output_low(nCS); // pull down CS -> select device
spi_write(command); // write command to SPI
spi_write(high_adress); // write higher part of read adress
spi_write(middle_adress);
spi_write(low_adress); // write lower part of read adress
low_adress = spi_read(0); // get data
output_high(nCS); // pull up CS -> de-select device
}
return(low_adress); // return read value
}
|
the full code to read the ID is:
Code: |
// SPI READ MANUFACTOR AND PRODUCT ID (ONE BYTE) =====================================
int16 spi_read_man_id(void) {
union ui8i16 id;
output_low(nCS); // pull down CS -> select device
spi_write(READ_MAN_PROD_ID); // write command to SPI
id.i8[1] = spi_read(0); // get data
id.i8[0] = spi_read(0); // get data
output_high(nCS); // pull up CS -> de-select device
return (id.i16);
}
|
for command i use (in dependency of the function)
Code: |
// instruction set of AT25F1024A
#define SET_WRITE_ENABLE_LATCH 0b00000110
#define RESET_WRITE_ENABLE_LATCH 0b00000100
#define READ_STATUS_REGISTER 0b00000101
#define WRITE_STATUS_REGISTER 0b00000001
#define READ_SEEPROM 0b00000011
#define WRITE_SEEPROM 0b00000010
#define ERASE_ONE_SECTOR 0b01010010
#define SEEPROM_ERASE 0b01100010
#define READ_MAN_PROD_ID 0b00010101
|
the function spi_read_man_id gives 0x1F60 back (this is the correct value).
I think that the Statusregister is set and read correct, but I´ve still problems with normal data.
greetings
2pi |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Tue Dec 20, 2005 10:45 am |
|
|
Quote: |
it was too early to cheer. there are still problems with the SPI.
|
I focussed my comments on the SPI routines only according to your previous observation.
I don't have time to check your whole code wich has conditionals statements that
I don't know where they come from.
Just to spot the problem, did you test that the basic SPI tasks are accomplished properly?
Something like this:
Code: |
WriteToSerialFlash(int24 address, int8 data);
int8 ReadFromSerialFlash(int24 address);
main()
{
address = 0;
data = 'a';
........
for(n = 0; n < 30; n++)
{
WriteToSerialFlash(address, data);
value = ReadFromSerialFlash(address);
printf(" %C", value);
address++; data++;
delay_ms(100);
}
}
|
Humberto |
|
|
2pi
Joined: 16 Dec 2005 Posts: 7 Location: vienna/austria
|
|
Posted: Tue Dec 20, 2005 11:14 am |
|
|
yeah i tried this!
it doesn´t work. i get 0x00 0x00 0xff 0xff 0xff 0xff 0xff ....
but it should be this in it: 0x00 0x01 0x02 0x03 ....
But reading the ID of the device works fine. the comeback value is 0x1f60. I can also set/reset the Statusregister of the device. this works also fine.
the kernel of the write routine is:
Code: |
output_low(nCS); // pull down CS -> select device
spi_write(SET_WRITE_ENABLE_LATCH);
spi_write(command); // write command to SPI
spi_write(high_adress); // write higher part of read adress
spi_write(middle_adress); // write higher part of read adress
spi_write(low_adress); // write lower part of read adress
spi_write(data); // write data
delay_us(1);
output_high(nCS); // pull up CS -> de-select device
}
delay_us(500);
|
and the kernel of the read function is:
Code: |
output_low(nCS); // pull down CS -> select device
spi_write(command); // write command to SPI
spi_write(high_adress); // write higher part of read adress
spi_write(middle_adress);
spi_write(low_adress); // write lower part of read adress
low_adress = spi_read(0); // get data
output_high(nCS); // pull up CS -> de-select device
}
return(low_adress); // return read value
|
with the defines from my older posting. did i forget something to do for writing/ reading ?
greetings
2pi |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Tue Dec 20, 2005 1:00 pm |
|
|
Ok, then you would back and use a foolproof way:
Code: |
{
command = 0x02;
BOB = 0x001000; // Beginning_Of_Block at address 0x001000
WREN = 0x06;
WRDI = 0x04;
data = 'a';
// Write Enable
output_low(nCS); // pull down CS -> select device
delay_us(10);
spi_write(WREN);
delay_us(10);
output_high(nCS); // pull up CS -> de-select device
// Data write cycle
output_low(nCS); // pull down CS -> select device
delay_us(10);
spi_write(command); // write command to SPI
WriteToSerialFlash(BOB, data);
for(n = 1; n<255; n++)
{
spi_write(data); // write 254 consecutives data
data+=1;
if(data>'Z')
{data = 'a';}
delay_us(10); // It is better to test if it is READY/BUSY
}
output_high(nCS); // pull up CS -> de-select device
delay_us(10);
// Write Disable
output_low(nCS); // pull down CS -> select device
delay_us(10);
spi_write(WRDI);
delay_us(10);
output_high(nCS); // pull up CS -> de-select device
}
|
Code not tested but hope you understand the idea.
Humberto |
|
|
|
|
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
|