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
解決済! 解決策の投稿を見る。
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.