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 >> |
\ | ||||||
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
Solved! Go to Solution.
Got it working! I had an inductive ringing effect (long wires all around the dev board). Added a 50 ohm resistor in series on the clock signal line and it works great now. Even at 10 MHz.
Got it working! I had an inductive ringing effect (long wires all around the dev board). Added a 50 ohm resistor in series on the clock signal line and it works great now. Even at 10 MHz.