I have the FRDM-KL05Z dev board and I'm trying to use AT25DF321A flash chip via SPI.
This is basically all the code I'm using:
uint8_t spi_ReadWriteByte(uint8_t data)
{
while (!(SPI0_BASE_PTR->S & SPI_S_SPTEF_MASK)); //wait TX to be empty
SPI0_BASE_PTR->D = data;
while (!(SPI0_BASE_PTR->S & SPI_S_SPRF_MASK)); //wait RX to be full
volatile uint8_t retData = SPI0_BASE_PTR->D;
return retData;
}
#define EXT_SELECT() MEM_CS_MODULE_BASE_ADDRESS->PCOR = MEM_CS_PORT_MASK
#define EXT_DESELECT() MEM_CS_MODULE_BASE_ADDRESS->PSOR = MEM_CS_PORT_MASK
| #define CMD_STATUS_READ |
|
0x05 |
| #define CMD_STATUS_WRITE |
0x01 |
| #define CMD_ERASE_CHIP |
|
0xC7 |
| #define CMD_WR_ENABLE |
|
0x06 |
| #define CMD_PROGRAM |
|
|
0x02 |
| #define CMD_READ |
|
|
0x03 |
static uint8_t readStatus();
| #define WAIT_WHILE_BUSY() |
while (readStatus() & 0x01) |
| #define SEND_ADDRESS(addr) |
|
|
|
|
|
|
\ |
|
|
|
spi_ReadWriteByte((addr >> 16) & 0xFF); |
\ |
|
|
|
spi_ReadWriteByte((addr >> & 0xFF); |
\ |
|
|
|
spi_ReadWriteByte(addr & 0xFF) |
| #define CMD(cmd) |
|
|
|
|
|
|
\ |
|
|
|
EXT_SELECT(); |
|
|
|
|
\ |
|
|
|
spi_ReadWriteByte(cmd); |
|
|
\ |
|
|
|
EXT_DESELECT() |
| #define CMD_AND_WRITE(cmd, x) |
|
|
|
\ |
|
|
|
EXT_SELECT(); |
|
|
|
|
\ |
|
|
|
spi_ReadWriteByte(cmd); |
|
|
\ |
|
|
|
spi_ReadWriteByte(x); |
|
|
\ |
|
|
|
EXT_DESELECT() |
| #define CMD_AND_READ(cmd, x) |
|
|
|
\ |
|
|
|
EXT_SELECT(); |
|
|
|
|
\ |
|
|
|
spi_ReadWriteByte(cmd); |
|
|
\ |
|
|
|
x = spi_ReadWriteByte(0xAA); |
\ |
|
|
|
EXT_DESELECT() |
static uint8_t readStatus()
{
|
uint8_t status; |
|
CMD_AND_READ(0x05, status); |
|
|
return status; |
}
void extRead(uint32_t address, uint8_t *buffer, uint16_t count)
{
|
EXT_SELECT(); |
|
spi_ReadWriteByte(CMD_READ); //read command |
|
SEND_ADDRESS(address); |
|
while (count --) *buffer++ = spi_ReadWriteByte(0x00); |
|
EXT_DESELECT(); |
}
static void extUnprotect(void)
{
|
CMD(CMD_WR_ENABLE); |
|
CMD_AND_WRITE(CMD_STATUS_WRITE, 0x00); |
}
void extWrite(uint32_t address, uint8_t *buffer, uint16_t count)
{
|
extUnprotect(); |
|
CMD(CMD_WR_ENABLE); |
|
|
|
EXT_SELECT(); |
|
spi_ReadWriteByte(CMD_PROGRAM); |
|
SEND_ADDRESS(address); |
|
while (count--) spi_ReadWriteByte(*buffer++); |
|
EXT_DESELECT(); |
|
|
|
WAIT_WHILE_BUSY(); |
}
void extErase(void)
{
|
extUnprotect(); |
|
CMD(CMD_WR_ENABLE); |
|
CMD(CMD_ERASE_CHIP); |
|
WAIT_WHILE_BUSY(); |
}
The erase function takes about 20-30 sec, so it seems to work well, but when I send auxBuffer over serial, all I get is 0xFF's.
rxBuffer containts the correct data, everything seems just fine, but it just won't work. I tried different addresses, but same thing.
SPI is working, status seems correct (0x10 - 1st byte, 0x00 - 2nd byte), and if I read manufacturer id, I get 0x1F, 0x47, 0x01, 0x00. I also tried different SPI clocks (from few 100 kHz to 10 MHz), tried 2 different chips and they have the same exact behavior, tried adding delays between/after asserting/deasserting /CS.
I also tried setting clock polarity to high (I'm using processor expert to initialize SPI) and when I write a page (256 bytes) of AA 55 AA 55's, I get in return 55 2A D5 2A D5 2A...
/Hold and /WP pins are tied to VCC.
I'm waiting for my logic analyzer delivery I just ordered. I think the problem is an uneven number of bits in the write command but I'm not really sure...
Any other suggestions until then?
Thanks