I hate it when people post questions, figure things out and then don't post the solution!!
I was able to get this working and have provided the .h and .c code used in order to make everything run. This EEPROM is incredibly finicky. I was able to get it to work at 2000KHz and 12.5KHz.
The code and a more detailed description is posted on my website @
http://comp-e.com/using-spi-eeprom-25aa512-on-an-hcs08-microcontroller
Hello,
I think that a few comments about the code posted on your website are in order. One of your preliminary comments:
You will notice that slave select pin is not used. Because I only used this one chip, I tied the SS, WP, and HOLD pins to hi/low as per my needs.
Tying the SS (or CS) pin low is not an option for an EEPROM device. The line must be lowered prior to the commencement of a command sequence (to indicate that a command byte will follow), and raised at the completion of the command sequence. For a write or erase command, execution will not commence until this occurs.
There still seems to be some confusion over the role of the SPI flags SPTEF and SPRF. My understanding is that many of the time delays that you have introduced should not be necessary, but were required because of improper handling of the SPRF flag. The amount of delay would also have been dependent on the SPI clock rate chosen. With appropriate handling of SPRF, the clock rate should be non-critical, provided it is less than the maximum limit specified for the EEPROM.
Now for some comments on snippets of your code, to outline some of the perceived problems -
Snippet 1:
void SPI_WREN(void)
{
CS_ON;
delay(2); // Probably unnecessary for EEPROM
while (!(SPIS & 0x20)); // Wait until ready to send
// SPTEF should normally be already set here
SPID = WREN; // Send byte value
delay(1);
// Delay is needed for completion of SPI transfer prior to raising CS
// A better solution is to test the SPRF flag
while (!(SPIS & 0x80)); // Wait until transfer is complete
(void)SPID; // Clears SPRF - prevents overrun on next transfer
CS_OFF;
delay(1); // Unnecessary
}
Snippet 2:
byte SPI_RDSR(void)
{
CS_ON;
delay(2); // Probably unnecessary for EEPROM
while (!(SPIS & 0x20)); // Wait until ready to send
// SPTEF should normally be already set here
SPID = RDSR; // Send byte value
while (!(SPIS & 0x20)); // Wait until ready to send
// SPTEF should again be set because of double buffering
SPID = DUMMY; // Send byte value
delay(1); // Unnecessary
while (!(SPIS & 0x80)); // Wait until ready to send
// SPRF will become set on completion of the first byte transfer
// SPID will contain the result of this transfer (invalid value)
// On completion of the second transfer, an overrun state will remain until SPRF is cleared
// The result of the second transfer will be lost
delay(4); // Unnecessary with appropriate SPRF handling
CS_OFF;
delay(1); // Unnecessary
return SPID; // This read will clear both SPRF and the overrun state
}
There are many other instances throughout the code with similar issues. The cardinal rule for SPI master transfers -
Wait until each byte transfer is complete, and then always clear the SPRF flag to prevent an overrun condition.
If this is strictly followed, there should be few timing issues. While I have not used the 25AA512 device, I have used smaller capacity SPI EEPROM devices - I cannot see that there are more severe timing requirements for the larger device, and I do not know of any special power-up requirements.
See what you make of the attached experimental code.
Regards,
Mac
I did retain control of the CS pin but the SS pin was tied since I didn't have a need for it.
I will try out your code as it's quite a bit cleaner, but I did try to follow your previous suggestion. Problem was, when I hooked it up to the logic analyzer the while( ... ) was clearing before the 8 clock tics finished going out.
Hello,
comp-e wrote:I did retain control of the CS pin but the SS pin was tied since I didn't have a need for it.
With the SPI configuration you have used, the SS pin function at the MCU does not exist. That pin will operate as GPIO, so there is no reason for tying anywhere. There is also no reason that the pin could not have been allocated to the CS output line function.
The reason for the ambiguity is that the labels SS and CS are often used to represent the same signal.
... Problem was, when I hooked it up to the logic analyzer the while( ... ) was clearing before the 8 clock tics finished going out.
For those instances where a flag is cleared by means of a read process, such as for SPRF, you may find that the debugger is unintentionally clearing the flag because it is reading the appropriate registers during the monitoring process, during single stepping. I suspect that this was a possible reason for your problem.
This can be avoided by not single stepping through the function, but using a break point at the conclusion of the function.
Regards,
Mac