|
|
View previous topic :: View next topic |
Author |
Message |
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
Problem writing/reading 93AA86C EEPROM |
Posted: Tue Mar 28, 2017 8:25 am |
|
|
I'm using the PIC16F1825 Development Kit from CCS. I ran the EX17 program with the included 93AA56 EEPROM and all worked ok. I then changed the EEPROM to a 93AA86C and changed the include file from 9356.c to 9386.c and I'm no longer writing to the EEPROM. The read appears to be working. The ORG pin on the 93AA86 is tied low so I'm using 8 bit organization.
Any help would be greatly appreciated.
Thanks in advance.
My code is as follows:
Code: | #include <16F1825.h>
#device ICD=TRUE
#use delay(clock=500KHz, int=500KHz)
//#use rs232(baud=9600, xmit=PIN_C4, rcv=PIN_C5)
#define EEPROM_SELECT PIN_C4
#define EEPROM_CLK PIN_C0
#define EEPROM_DI PIN_C1
#define EEPROM_DO PIN_C2
#include <9386C.c>
#define GREEN_LED PIN_C2
#define YELLOW_LED PIN_C1
#define RED_LED PIN_C0
#define PUSH_BUTTON PIN_C3
typedef enum {GREEN, YELLOW, RED} colors;
void light_one_led(colors led)
{
output_high(GREEN_LED);
output_high(YELLOW_LED);
output_high(RED_LED);
switch(led)
{
case GREEN : output_low(GREEN_LED); break;
case YELLOW : output_low(YELLOW_LED); break;
case RED : output_low(RED_LED); break;
}
}
void wait_for_one_press(void)
{
while (input(PUSH_BUTTON));
delay_ms(100);
while (!input(PUSH_BUTTON));
}
void show_binary_on_leds(int n)
{
output_high(GREEN_LED);
output_high(YELLOW_LED);
output_high(RED_LED);
If (bit_test(n,0) )
output_low(GREEN_LED);
If (bit_test(n,1) )
output_low(YELLOW_LED);
If (bit_test(n,2) )
output_low(RED_LED);
}
void main(void)
{
int count;
setup_adc_ports(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
init_ext_eeprom();
count = read_ext_eeprom(0);
while (TRUE)
{
show_binary_on_leds(count);
wait_for_one_press();
count++;
write_ext_eeprom(0, count);
}
} |
9386.c code is:
Code: | #ifndef EEPROM_SELECT
#define EEPROM_SELECT PIN_B4
#define EEPROM_CLK PIN_B2
#define EEPROM_DI PIN_B1
#define EEPROM_DO PIN_B0
#endif
#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 2048
void init_ext_eeprom() {
BYTE cmd[2];
BYTE i;
output_low(EEPROM_DI);
output_low(EEPROM_CLK);
output_low(EEPROM_SELECT);
cmd[0]=0x00;
cmd[1]=0x26;
for(i=1;i<=2;++i)
shift_left(cmd,2,0);
output_high(EEPROM_SELECT);
for(i=1;i<=14;++i) {
output_bit(EEPROM_DI, shift_left(cmd,2,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
output_low(EEPROM_DI);
output_low(EEPROM_SELECT);
}
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) {
BYTE cmd[4];
BYTE i;
cmd[0]=data;
cmd[1]=address;
cmd[2]=(address>>8);
cmd[3]=0x5;
for(i=1;i<=5;++i)
shift_left(cmd,4,0);
output_high(EEPROM_SELECT);
for(i=1;i<=27;++i) {
if(i<4 || i>8)
{
output_bit(EEPROM_DI, shift_left(cmd,4,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
else
shift_left(cmd,4,0);
}
output_low(EEPROM_DI);
output_low(EEPROM_SELECT);
delay_ms(11);
}
BYTE read_ext_eeprom(EEPROM_ADDRESS address) {
BYTE cmd[4];
BYTE i,data;
cmd[0]=0;
cmd[1]=address;
cmd[2]=(address>>8);
cmd[3]=0x6;
for(i=1;i<=5;++i)
shift_left(cmd,4,0);
output_high(EEPROM_SELECT);
for(i=1;i<=27;++i) {
if(i<4 || i>8)
{
output_bit(EEPROM_DI, shift_left(cmd,4,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
if(i>19)
shift_left(&data,1,input(EEPROM_DO));
}
else
shift_left(cmd,4,0);
}
output_low(EEPROM_SELECT);
return(data);
} |
Last edited by Aileyus on Tue Mar 28, 2017 10:25 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19477
|
|
Posted: Tue Mar 28, 2017 8:58 am |
|
|
Since you've got the 'C' version, you do realise you have to pull the PE pin up to logic 1, or the chip is fully protected?.... |
|
|
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
|
Posted: Tue Mar 28, 2017 11:02 am |
|
|
Ttelmah wrote: | Since you've got the 'C' version, you do realise you have to pull the PE pin up to logic 1, or the chip is fully protected?.... |
Yes. I'm sorry, I forgot to add that in my post. the PE pin is pulled to VCC.
Thanks.
I'm not sure what the code is writing in the init_ext_eeprom() module. I'm still trying to decipher 0x26 relative to the chart in the chip's datasheet. Is it 1 00 110x xxxx xxxx? If so, that should be the write enable command.
I'm a little confused about the shift_left function. I would think the word would be shifted fully to the left before the bits are outputted as the 0x26 is the command. Looks kind of awkward to leave it to the right before outputting. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19477
|
|
Posted: Tue Mar 28, 2017 11:24 am |
|
|
Whoa.
0x26?.
That is the command from 9386.c, not the command from 9386c.c
Yet you show yourself including 9386c.c?...
init for the 9386c is very different from the one you post.
Which one are you including?. |
|
|
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
|
Posted: Tue Mar 28, 2017 11:51 am |
|
|
Ttelmah wrote: | Whoa.
0x26?.
That is the command from 9386.c, not the command from 9386c.c
Yet you show yourself including 9386c.c?...
init for the 9386c is very different from the one you post.
Which one are you including?. |
I edited my original post to state the 9386.c. I had tried them both and neither worked but when I was reading the 9386C.c code I realized it was for the 16 bit "organization" and I'm using 8 bits. Then I went back to the 9386.c
Sorry for the confusion. Also, I've since figured out that since 0x26 is one byte and I'm only loading one byte per cmd[], the shift left 2 times aligns the word to the left correctly. I'll assume that the init is working and now start studying the write statement which is also confusing as I really don't have a clear description as to what the write data format is. This isn't really SPI and the datasheet isn't clear enough.
Update:
I put a scope on DO (C2) and it is following the green LED status since it controls the green LED. DO is not toggling during write. I can't imagine that C2 is having difficulties with being associated to two outputs when DI (C1) also has two functions (yellow LED) and I'm not having any read problems. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19477
|
|
Posted: Tue Mar 28, 2017 2:11 pm |
|
|
You can't do dual functions on the I2C output line. It has to be _tri_state_ (undriven), when the master is not driving it, to allow the handshake to work.... |
|
|
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
|
Posted: Tue Mar 28, 2017 3:01 pm |
|
|
It seems the problem is nobody has ever debugged this 9386 driver. All three commands talk only to DI. DO is not used at all in this driver. That just doesn't make any sense.
I corrected the DO/DI issue and I see other issues.
1) The clock pauses toggling during the command portion of the read and write commands. The clock toggles normally during the command portion of the EWEN command. I have since fixed this.
2) With the DO looking correct to write exactly what it should be writing, I'm seeing a read of 0 on DI with the scope and yet my data is 0xFF. I'm not sure how to fix this yet.
Uhm, this driver is hosed. I doubt this thing thing could have ever been tested. I doubt this thing could have ever work. CCS???
This is the current 9386.c
Code: |
#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 2048
void init_ext_eeprom() {
BYTE cmd[2];
BYTE i;
output_low(EEPROM_DO);
output_low(EEPROM_CLK);
output_low(EEPROM_SELECT);
cmd[0]=0x00;
cmd[1]=0x26;
for(i=1;i<=2;++i)
shift_left(cmd,2,0);
output_high(EEPROM_SELECT);
for(i=1;i<=14;++i) {
output_bit(EEPROM_DO, shift_left(cmd,2,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
output_low(EEPROM_DO);
output_low(EEPROM_SELECT);
}
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) {
BYTE cmd[4];
BYTE i;
cmd[0]=data;
cmd[1]=address;
cmd[2]=(address>>8);
cmd[3]=0x5;
for(i=1;i<=5;++i)
shift_left(cmd,4,0);
output_high(EEPROM_SELECT);
for(i=1;i<=27;++i) {
if(i<4 || i>8)
{
output_bit(EEPROM_DO, shift_left(cmd,4,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
else
{
shift_left(cmd,4,0);
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
}
output_low(EEPROM_DO);
output_low(EEPROM_SELECT);
delay_ms(11);
}
BYTE read_ext_eeprom(EEPROM_ADDRESS address) {
BYTE cmd[4];
BYTE i,data;
cmd[0]=0;
cmd[1]=address;
cmd[2]=(address>>8);
cmd[3]=0x6;
for(i=1;i<=5;++i)
shift_left(cmd,4,0);
output_high(EEPROM_SELECT);
for(i=1;i<=27;++i) {
if(i<4 || i>8)
{
output_bit(EEPROM_DO, shift_left(cmd,4,0));
if(i>19)
{
shift_left(&data,1,input(EEPROM_DI));
}
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
else
{
shift_left(cmd,4,0);
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
}
output_low(EEPROM_SELECT);
return(data);
}
|
|
|
|
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
|
Posted: Tue Mar 28, 2017 3:10 pm |
|
|
Ttelmah wrote: | You can't do dual functions on the I2C output line. It has to be _tri_state_ (undriven), when the master is not driving it, to allow the handshake to work.... |
This is CCS's development kit and their code (driver). It worked fine with the memory chip (and its associated driver) in the development kit. I think the problem is the driver for the 9386 is fubar. Someone wrote it and threw it over the fence without ever testing it. SPI won't work only talking to DI and CLK.
I'm much closer but I'm still not sure if the chip is actually being written to. It seems that when I corrected the clock stalling, the command data (DO) is staying high longer than expected.
I'm certainly not getting out (into the data variable) what I'm seeing on the scope during the read cycle. The command data (DO) doesn't stay high longer than expected on the read. Could be a hint.
At least the clock no longer goes to bed during the read and write cycles. |
|
|
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
|
Posted: Tue Mar 28, 2017 4:00 pm |
|
|
I shut off all the calls to output to C1. I then tried to tri-state C1 using set_tris_c(0x02) but C1 is still high and does not change during a read cycle. C1 is DI. Any ideas? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Mar 28, 2017 4:15 pm |
|
|
Quote: | The three commands talk only to DI. DO is not used at all in this driver. |
That's not true. Look closely at the read_ext_eeprom() routine that
you posted in your first post. It uses both pins:
Quote: | if(i<4 || i>8)
{
output_bit(EEPROM_DI, shift_left(cmd,4,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
if(i>19)
shift_left(&data,1,input(EEPROM_DO));
}
|
The 2nd thing is I don't think you understand CCS's pin naming mentality.
When they say "EEPROM_DI", they mean data leaving the PIC and going
to the eeprom. Your MOSI pin on the PIC should be connected to the
EEPROM_DI pin. The EEPROM_DO pin is the MISO pin (Master in, Slave Out).
You can see this in the routine above. They are sending the command
to the "Data In" pin on the eeprom. Then, if i >19, they read data from
the "Data Out" pin on the eeprom.
If you look at the CCS driver file 9356bitbang.c, you'll see comments
added by CCS to show which pins are MOSI and MISO:
Code: |
#define EEPROM_SELECT PIN_B4
#define EEPROM_CLK PIN_B2
#define EEPROM_DI PIN_B1 //mosi
#define EEPROM_DO PIN_B0 //miso |
|
|
|
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
|
Posted: Wed Mar 29, 2017 7:32 am |
|
|
PCM programmer wrote: |
Quote: | The three commands talk only to DI. DO is not used at all in this driver. |
That's not true. Look closely at the read_ext_eeprom() routine that
you posted in your first post. It uses both pins:
if(i<4 || i>8)
{
output_bit(EEPROM_DI, shift_left(cmd,4,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
if(i>19)
shift_left(&data,1,input(EEPROM_DO));
}
|
Oops! I guess I missed that too.
Quote: |
The 2nd thing is I don't think you understand CCS's pin naming mentality.
When they say "EEPROM_DI", they mean data leaving the PIC and going
to the eeprom. Your MOSI pin on the PIC should be connected to the
EEPROM_DI pin. The EEPROM_DO pin is the MISO pin (Master in, Slave Out).
|
AHA! There in lies the rub. I'm misunderstanding CCS's pin naming convention. Well, actually, I need an anal-cranial extraction. That only makes sense when you think about it. I just wasn't thinking.
Thanks. I'll give that a try this morning and see if it doesn't work out better.
I still think this driver has never been used before. There were multiple problems with it.
Last edited by Aileyus on Wed Mar 29, 2017 7:57 am; edited 1 time in total |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Mar 29, 2017 7:49 am |
|
|
Quote: | I still think this driver has never been used before. There were multiple problems with it. |
It is best not to consider CCS supplied code as "drivers" as they are not guaranteed fully tested/may not work in user applications "straight out of the box", have no defined interface, generally won't work with each other and may not implement all the functions of the device. Instead they are example code to get developers started, for them to expand, improve and integrate with other code as required.
Realistically, it is still a requirement and an expectation for embedded developers to understand the hardware they are working with: to understand datasheets and technical data and to be able to write/modify code to meet the requirements of the project. The era of embedded programmers plugging fully tested drivers with well-developed interfaces into their code and writing a little glue-code to hold it together and implement project-specific logic is not quite here yet, and to be fair, is still some way off. CCS only goes a very little way along that path, and I strongly doubt such a plug and play system was the intent of CCS C's developers. |
|
|
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
|
Posted: Wed Mar 29, 2017 8:25 am |
|
|
I understand that. It should actually read and write to the chip though. I'm not really strongly exercising this code. I'm just trying to understand how to read and write to a new format and what they give me should be correct even if incomplete.
For example, can you imagine if your text books were wrong? What would you actually be learning? What if the datasheets were wrong? What would you actually be building? Incorrect information reduces the developer to a hack by definition. Another example is I need to give you correct information in order for you to correctly help me fix my mistakes.
Incomplete is ok. Incorrect, not so much.
Thanks for your help. I have fixed the DO/DI but I'm still not reading back the data I'm writing. No matter what I write, I'm still reading back 0x1F. In both cases I'm writing and reading to address 0x000 as verified on a scope. I tried to post screen shots of the scope traces but I'm not sure how to upload the screen shots into this forum.
Here is the latest 'driver'.
Code: |
#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 2048
void init_ext_eeprom() {
BYTE cmd[2];
BYTE i;
output_low(EEPROM_DO);
output_low(EEPROM_CLK);
output_low(EEPROM_SELECT);
cmd[0]=0x00;
cmd[1]=0x26;
for(i=1;i<=2;++i)
shift_left(cmd,2,0);
output_high(EEPROM_SELECT);
for(i=1;i<=14;++i) {
output_bit(EEPROM_DI, shift_left(cmd,2,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
output_low(EEPROM_DI);
output_low(EEPROM_SELECT);
}
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) {
BYTE cmd[4];
BYTE i;
cmd[0]=data;
cmd[1]=address;
cmd[2]=(address>>8);
cmd[3]=0x5;
for(i=1;i<=5;++i)
shift_left(cmd,4,0);
output_high(EEPROM_SELECT);
for(i=1;i<=27;++i) {
// if(i<4 || i>8)
// {
output_bit(EEPROM_DI, shift_left(cmd,4,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
/* }
else
{
shift_left(cmd,4,0);
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
*/
}
output_low(EEPROM_DI);
output_low(EEPROM_SELECT);
delay_ms(11);
}
BYTE read_ext_eeprom(EEPROM_ADDRESS address) {
BYTE cmd[4];
BYTE i,data;
cmd[0]=0;
cmd[1]=address;
cmd[2]=(address>>8);
cmd[3]=0x6;
for(i=1;i<=5;++i)
shift_left(cmd,4,0);
output_high(EEPROM_SELECT);
for(i=1;i<=27;++i) {
// if(i<4 || i>8)
// {
output_bit(EEPROM_DI, shift_left(cmd,4,0));
if(i>19)
{
shift_left(&data,1,input(EEPROM_DO));
}
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
// }
// else
// {
// shift_left(cmd,4,0);
// output_high(EEPROM_CLK);
// output_low(EEPROM_CLK);
// }
}
output_low(EEPROM_SELECT);
return(data);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 29, 2017 8:47 am |
|
|
1. You didn't post your pins. Post the list of #defines for your PIC pins
that go to the eeprom.
2. Also post a list of connections between the PIC pins and eeprom pins.
Tell us your eeprom package, since pinouts vary between them. Also
tell us your PIC package. Example of the level of detail I'd like to see:
Pin C2 on the 16F1825 (PDIP package) connects to the DO pin on
the eeprom pin 4 (PDIP package).
.
.
.
etc.
Check the connections with an ohmmeter to verify them before posting.
3. Also, tell us what eeprom you are currently using. Is it the 93AA56 or
the 93AA86C ?
4. What is the Vdd voltage of the PIC and the eeprom ?
5. I noticed something from your first post. You have LEDs tacked on
the signal lines for the eeprom. I wouldn't do that. You have high-speed
signals and you're loading them down with LEDs. Remove all the LEDs. |
|
|
Aileyus
Joined: 23 Mar 2017 Posts: 27
|
|
Posted: Wed Mar 29, 2017 9:58 am |
|
|
Having reviewed the microwire format, I have gone back to the original driver and see why they did what they did. I now see the signals correct as per the mircowire format. The chip still does not read back what is written to it. I'm not sure if the read is failing or the write is failing as the signals look correct.
Before I went back to the original driver I was able to verify that I was in fact writing to the memory. The problem was I was offset in the data on write and read. That's when I realized why they stopped the clock in the original driver code. Awkward but it works as everything works off the clock, not absolute time.
My scope is connected at the memory chip which is on the development chocolate board.
PCM programmer wrote: | 1. You didn't post your pins. Post the list of #defines for your PIC pins
that go to the eeprom.
|
Code: |
#define EEPROM_SELECT PIN_C4
#define EEPROM_CLK PIN_C0
#define EEPROM_DI PIN_C1
#define EEPROM_DO PIN_C2
|
Quote: |
2. Also post a list of connections between the PIC pins and eeprom pins.
Tell us your eeprom package, since pinouts vary between them. Also
tell us your PIC package. Example of the level of detail I'd like to see:
Pin C2 on the 16F1825 (PDIP package) connects to the DO pin on
the eeprom pin 4 (PDIP package).
.
.
.
etc.
|
The EEPROM is 93AA86C and is the 8 pin DIP so it will plug into the development chocolate board. The PIC is the PIC on the 16F1825 development kit pc board.
93AA86
Pin 1 (CS) is connected to C4
Pin 2 (CLK) is connected to C0
Pin 3 (DI) is connected to C1
Pin 4 (DO) is connected to C2
Pin 5 (VSS) is connected to ground
Pin 6 (ORG) is connected to ground (8 bit)
Pin 7 (WE) is connected to VCC
Pin 8 (VCC) is connected to VCC
I actually double checked each of these connections to ensure I wrote it as I have them connected. This goes to my comment about giving you correct information. It's a bear to troubleshoot with bogus feedback. Thanks for your efforts.
I have forgone the ohmmeter check as I'm looking at the pins on the memory chip with a scope so I'm certain the connections are making contact.
Just for the record, while I'm completely new to this microwire format (and relatively new to SPI and I2C) I'm an analog motor controls designer who can write code. I have my MSEE and I'm soon to be crawling into retirement. I've been doing electronics for over 50 years. This is not to say that I can't still do stupid things (as I've already clearly shown). It's just to help you calibrate whether you're giving instructions to a clueless newbe or senile EE. I'm the senile one.
Quote: | 3. Also, tell us what eeprom you are currently using. Is it the 93AA56 or
the 93AA86C ?
|
93AA86C
Quote: |
4. What is the Vdd voltage of the PIC and the eeprom ? |
It's the 5V from the development kit pc board. I just measured it and it's pretty close to 5V (maybe 5.05V - I don't trust the accuracy of my PC Oscilloscope but it's good enough for government work). |
|
|
|
|
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
|