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

SPI Problem with ATMEL AT25F1024A [solved]
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
2pi



Joined: 16 Dec 2005
Posts: 7
Location: vienna/austria

View user's profile Send private message Visit poster's website

SPI Problem with ATMEL AT25F1024A [solved]
PostPosted: Fri Dec 16, 2005 6:51 am     Reply with quote

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







PostPosted: Fri Dec 16, 2005 9:27 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Dec 16, 2005 10:03 am     Reply with quote

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







PostPosted: Fri Dec 16, 2005 10:17 am     Reply with quote

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

View user's profile Send private message Visit poster's website

Thank you for the fast response!
PostPosted: Fri Dec 16, 2005 11:55 am     Reply with quote


@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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Dec 16, 2005 7:46 pm     Reply with quote

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







PostPosted: Sat Dec 17, 2005 3:23 am     Reply with quote

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

View user's profile Send private message Visit poster's website

Problem solved
PostPosted: Mon Dec 19, 2005 1:45 am     Reply with quote


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







PostPosted: Mon Dec 19, 2005 3:58 am     Reply with quote

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

View user's profile Send private message Visit poster's website

still problems ...
PostPosted: Tue Dec 20, 2005 7:40 am     Reply with quote


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

View user's profile Send private message

PostPosted: Tue Dec 20, 2005 9:14 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 20, 2005 9:49 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 20, 2005 10:45 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Tue Dec 20, 2005 11:14 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 20, 2005 1:00 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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