View previous topic :: View next topic |
Author |
Message |
Guest
|
PIC24 to Atmel flash SPI issue |
Posted: Mon Sep 14, 2009 12:13 pm |
|
|
Hi,
I've been trying to read/write data from my PIC24 to an Atmel AT25F2048 SPI Serial Flash through SPI, but I have been having a communication issue. I have written the following simple piece of code which should read the product ID. On the oscilloscope I can see that the correct opcode is being sent, the clock is cycling/CS is low while writing the 1 byte opcode and CS is sent high to complete the write, but the product ID is never being received back:
Code: |
#include <24fj128ga006.h>
#device ICD=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#use delay(internal=8M)
#define EEPROM_SELECT PIN_G9
#define EEPROM_DI PIN_G7
#define EEPROM_DO PIN_G8
#define EEPROM_CLK PIN_G6
// Use Charlie U's SPI mode definitions.
#define SPI_MODE_0_0 0x4000
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0010
#define SPI_MODE_1_1 0x4010
unsigned int16 ID;
void main()
{
setup_spi2( FALSE );
setup_spi2(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16);
output_high(EEPROM_SELECT);
while(true)
{
output_low(EEPROM_SELECT);
ID = spi_read2(0x15);
output_high(EEPROM_SELECT);
delay_ms(5);
}
}
|
I've tried some other SPI examples with no success. I've been going in circles for a few weeks now trying to get SPI to work with this Atmel EEPROM. Any help and/or examples that you may be able to provide to me on this issue will be greatly appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Sep 14, 2009 12:17 pm |
|
|
Those SPI #defines are from a fairly old post. They are tied to the
particular register bit layout of the 16F (and 18F) series PICs.
I would not try to use them with the 24F-series PICs, at least without
checking it first.
In fact, look at FvM's post on using hardware SPI with the 24F-series:
http://www.ccsinfo.com/forum/viewtopic.php?t=38491&start=12 |
|
|
Guest
|
|
Posted: Mon Sep 14, 2009 1:10 pm |
|
|
Thanks so much for the quick response.
I've looked at the data sheet to determine the appropriate pins to use for the SPI setup. I've read the other post that you've referred to, but I get a bit lost in some of the details that they are pointing out with the incorrect SDI pin select register and how to diagnose this. I'm fairly new to embedded programming, so any detailed guidance that you may have on checking to see if this is an issue or another alternative solution is greatly appreciated. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Sep 14, 2009 1:54 pm |
|
|
Yes, the above SPI_MODE codes are not applicable to PIC24.
With PCD, the setup_spi mask is directly copied to SPIxCON1, in my opinion you find the correct coding below, but you can check in PIC24F Family Reference Manual
Code: | #define SPI_MODE_0_0 0x0100
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0140
#define SPI_MODE_1_1 0x0040 |
The next point are #pin_select statements, but they aren't required for
PIC24FGA006, that has fixed pins.
Finally, your ID read operation is incorrect in my understanding of the AT25F2048 datasheet. But I'm using a different SPI flash device.
Code: | ID = spi_read2(0x15); |
I think, that you need three byte transfers to get all data.
Code: | spi_read2(0x15);
ID1 = spi_read2(0);
ID2 = spi_read2(0); |
|
|
|
Guest
|
|
Posted: Mon Sep 14, 2009 2:30 pm |
|
|
Thanks for the details FvM.
It's my understanding from looking at the Atmel datasheet that the RDID opcode can be either 0x15 or 0x1D. I'm still unsure if I have connectivity to the Atmel memory at this point and was hoping that this would be a simple test. I've emailed Atmel tech support twice over the past week with no answer as of today. I haven't been able to detect any hardware issues. I'm running out of options at this point and am desperate to get this working. Any other advice you or anyone else can give is greatly appreciated. |
|
|
Guest
|
|
Posted: Mon Sep 14, 2009 2:34 pm |
|
|
Sorry, I didn't see you last solution. I will try that now. |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Sep 15, 2009 6:18 am |
|
|
Quote: | I didn't see you last solution. |
I added a supplement later on. If I understand the Atmel datasheet correctly, the ID isn't on a byte boundary in this case. But you can try to match it, if you get data different from 0x00 or 0xFF, otherwise, you most likely didn't manage to access the chip. |
|
|
Guest
|
|
Posted: Tue Sep 15, 2009 8:36 am |
|
|
Excellent!! It appears to be reading in the proper product ID at this point. I'm getting 1F 63. Thank you FvM and PCM programmer for all your advice. I've been spinning my wheels for quite some time now.
At this point I'm going to write up and test some fairly simple read/write routines. I've tried in the past with no success. Hopefully, I can get this to work now. If you have any suggestions on some simple routines just let me know.
Thanks again!
New code:
Code: |
#include <24fj128ga006.h>
#device ICD=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#use delay(internal=8M)
#define EEPROM_SELECT PIN_G9
#define SPI_MODE_0_0 0x0100
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0140
#define SPI_MODE_1_1 0x0040
unsigned int16 ID1, ID2;
void main()
{
setup_spi2( FALSE );
setup_spi2(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_16);
output_high(EEPROM_SELECT);
while(true)
{
output_low(EEPROM_SELECT);
spi_read2(0x15);
ID1 = spi_read2(0);
ID2 = spi_read2(0);
output_high(EEPROM_SELECT);
delay_ms(5);
}
}
|
|
|
|
Guest
|
|
Posted: Fri Sep 18, 2009 8:06 am |
|
|
I've written some simple routines to read/write a byte of data successfully by using the CCS spi_read function. Now I need to write an entire page of data (256 bytes) to the same address and I know that the spi_read function is designed to send 1 byte of data for each call. I'm trying to decide which is the best way to accomplish this and was curious if the spi_read function can be used within a loop to accomplish this task. As a test I've attempted to send two byes of data to the same address by use of the spi_read function without success.
Any suggestions? |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Sep 18, 2009 9:06 am |
|
|
I don't know, what sending two bytes to same address means, the flash device it'self is performing an auto-increment of addresses.
A page write can work like below, assuming the memory has been erased before.
Code: | SPI_nCS_LAT = 0;
spi_read(0x06); // WREN
SPI_nCS_LAT = 1;
SPI_nCS_LAT = 0;
spi_read(0x02); // Page Program
spi_read(eeaddr.b[2]);
spi_read(eeaddr.b[1]);
spi_read(eeaddr.b[0]);
for (i=0; i<256; i++)
{
b = *data++;
spi_read(b);
}
SPI_nCS_LAT = 1; |
The reason for performing write action through the spi_read() function has been discussed in a previous thread, it has been necessary at least with previous PCD versions, but is still with most recent V4.099, if I remember right. It doesn't harm anyway. |
|
|
Guest
|
|
Posted: Fri Sep 18, 2009 1:55 pm |
|
|
Thank you for the example. I've used similar code to accomplish the task.
Within the last post I meant to say that I was assigning one address then writing two bytes of data. Sorry about that.
I can confirm that the spi_write function still seems not to work as intended within PCD version 4.097. I've only been using the spi_read function for read/write and it's been working perfectly.
Thanks again! |
|
|
|