NAND Flash K60 Using
本系统使用了Freescale(NXP)的MK60D系列芯片+Keil的IDE编译环境+YANDLD编写的K60库
硬件接法
程序
*初始化、读取芯片信息
/* 初始化SPI接口 */
SPI_QuickInit(SPI2_SCK_PD12_SOUT_PD13_SIN_PD14, kSPI_CPOL0_CPHA0, 30*1000*1000);
/* 初始化片选*/
PORT_PinMuxConfig(HW_GPIOD, 15, kPinAlt2); /* SPI2_PCS1 */
/* 获取SPI-Flash信息 */
if(w25qxx_init(HW_SPI2, HW_SPI_CS1))
{
printf("w25qxx device no found!
");
}
else
{
struct w25qxx_attr_t w25qxx;
w25qxx_get_attr(&w25qxx);
printf("%s(0x%X) detected!
", w25qxx.name, w25qxx.id);
printf("total size:%dKB
", w25qxx.size/1024);
printf("block size:%dKB
", w25qxx.block_size/1024);
printf("sector size:%d
", w25qxx.sector_size);
printf("page size:%d
", w25qxx.page_size);
buf_size = sizeof(buf);
block = w25qxx.size/buf_size;
}
w25qxx_attr_t类型的结构体,在w25qxx.h中定义:
struct w25qxx_attr_t
{
const char* name;
uint32_t size;
uint16_t id;
uint32_t page_size;
uint32_t sector_size;
uint32_t block_size;
};
w25qxx_init(HW_SPI2, HW_SPI_CS1)函数中包括SPI选择、SPI模式、SPI片选、w25qxx_probe()获取芯片的信息:
int w25qxx_init(uint32_t instance, uint32_t cs)
{
w25_dev.spi_instance = instance;
w25_dev.spi_cs = cs;
SPI_CTARConfig(instance, HW_CTAR0, kSPI_CPOL0_CPHA0, 8, kSPI_MSB, 30*1000*1000);
return w25qxx_probe();
}
再来看其中的w25qxx_probe()如何获取芯片信息:
static int w25qxx_probe(void)
{
uint32_t i;
uint16_t id;
uint8_t buf[2];
spi_xfer(W25X_ManufactDeviceID, kSPI_PCS_KeepAsserted);
spi_xfer(0, kSPI_PCS_KeepAsserted);
spi_xfer(0, kSPI_PCS_KeepAsserted);
spi_xfer(0, kSPI_PCS_KeepAsserted);
buf[0] = spi_xfer(0, kSPI_PCS_KeepAsserted);
buf[1] = spi_xfer(0, kSPI_PCS_ReturnInactive);
id = ((buf[0]<<8) + buf[1]);
W25QXX_TRACE("ID:0x%X
", id);
for(i = 0; i< ARRAY_SIZE(w25qxx_tbl);i++)
{
if(w25qxx_tbl[i].id == id)
{
w25_dev.attr = w25qxx_tbl[i];
w25qxx_power_up();
buf[0] = w25qxx_read_sr();
W25QXX_TRACE("SR:0x%X
", buf[0]);
buf[0] = w25qxx_read_sr2();
W25QXX_TRACE("SR2:0x%X
", buf[0]);
w25qxx_write_sr(0x00);
return 0;
}
}
return 1;
}
通过:
/* read id */
spi_xfer(W25X_ManufactDeviceID, kSPI_PCS_KeepAsserted);
spi_xfer(0, kSPI_PCS_KeepAsserted);
spi_xfer(0, kSPI_PCS_KeepAsserted);
spi_xfer(0, kSPI_PCS_KeepAsserted);
buf[0] = spi_xfer(0, kSPI_PCS_KeepAsserted);
buf[1] = spi_xfer(0, kSPI_PCS_ReturnInactive);
id = ((buf[0]<<8) + buf[1]);
W25QXX_TRACE("ID:0x%X
", id);
获取芯片的ID信息,ID信息通过SPI访问芯片内部预先写好的寄存器
#define W25X_DeviceID 0xAB
然后根据ID查表,进行进一步匹配来获取芯片的其他信息:
//W25系列芯片信息
static const struct w25qxx_attr_t w25qxx_tbl[] =
{
{"W25Q10", 128*1024, 0xEF10, 256, 4096, (64*1024)},
{"W25Q20", 256*1024, 0xEF11, 256, 4096, (64*1024)},
{"W25Q40", 512*1024, 0xEF12, 256, 4096, (64*1024)},
{"W25Q80", 1024*1024, 0xEF13, 256, 4096, (64*1024)},
{"W25Q16", 2048*1024, 0xEF14, 256, 4096, (64*1024)},
{"W25Q32", 4096*1024, 0xEF15, 256, 4096, (64*1024)},
{"W25Q64", 8192*1024, 0xEF16, 256, 4096, (64*1024)},
{"W25Q128", 16384*1024, 0xEF17, 256, 4096, (64*1024)},
};
读写Flash
预先设置两个buff,buf用来写入Flash,buf2用来读取Flash
static uint8_t buf[4*512];
static uint8_t buf2[4*512];
再对buf进行赋初值:
for(j=0;jj++)
{
buf[j] = j % 0xFF;
}
新建两个变量:block,buf_size
uint32_t block,buf_size;
buf_size = sizeof(buf);
block = w25qxx.size/buf_size;
此处,block不是Flash的硬件Block,而是指将整个Flash根据Buf的大小,分为几块,故block = w25qxx.size/buf_size;
再写入数据,写入第3个block:
w25qxx_write(3*block, buf, buf_size);
再读取数据,并显示:
w25qxx_read(3*block, buf2, buf_size);
for(j=0;jprintf("writeData %d:%d------",j,buf[j]);
printf("readData %d:%d
",j,buf2[j]);
}
效果: