//芯片探测 static int w25qxx_probe(void) { uint32_t i; uint16_t id; uint8_t buf[2]; /* read id */ spi_xfer(W25X_ManufactDeviceID, W25QXX_CS_LOW); spi_xfer(0, W25QXX_CS_LOW); spi_xfer(0, W25QXX_CS_LOW); spi_xfer(0, W25QXX_CS_LOW); buf[0] = spi_xfer(0, W25QXX_CS_LOW); buf[1] = spi_xfer(0, W25QXX_CS_HIGH); id = ((buf[0]<<8) + buf[1]); W25QXX_TRACE("ID:0x%X\r\n", id); //see if we find a match for(i = 0; i< ARRAY_SIZE(w25qxx_tbl);i++) { if(w25qxx_tbl[i].id == id) { /* find a match */ w25_dev.attr = w25qxx_tbl[i]; w25qxx_power_up(); buf[0] = w25qxx_read_sr(); W25QXX_TRACE("SR:0x%X\r\n", buf[0]); buf[0] = w25qxx_read_sr2(); W25QXX_TRACE("SR2:0x%X\r\n", buf[0]); // enable full access to all memory regin, something like unlock chip. w25qxx_write_sr(0x00); return 0; } } return 1; }
//芯片探测 int w25qxx_probe(void) { uint32_t i; uint16_t id; uint8_t buf[4]; buf[0] = W25X_ManufactDeviceID; buf[1] = 0; buf[2] = 0; buf[3] = 0; /* read id */ spi_write(&device, buf, 4, false); spi_read(&device, buf, 2, true); id = ((buf[0]<<8) + buf[1]); W25QXX_TRACE("ID:%d\r\n", id); //see if we find a match for(i = 0; i< ARRAY_SIZE(w25qxx_attr_table);i++) { if(w25qxx_attr_table[i].id == id) { // find a match w25qxx_type.name = w25qxx_attr_table[i].name; w25qxx_type.id = w25qxx_attr_table[i].id; w25qxx_type.size = w25qxx_attr_table[i].size; w25qxx_power_up(); buf[0] = w25qxx_read_sr(); W25QXX_TRACE("SR:0x%X\r\n", buf[0]); buf[0] = w25qxx_read_sr2(); W25QXX_TRACE("SR2:0x%X\r\n", buf[0]); // enable full access to all memory regin, something like unlock chip. w25qxx_write_sr(0x00); return SPI_EOK; } } return SPI_ERROR; }
//写数据 static int w25qxx_write_no_check(uint32_t addr, uint8_t *buf, uint32_t len) { uint16_t pageremain; W25QXX_TRACE("w25qxx - write_no_check: addr:%d len:%d\r\n", addr, len); pageremain = w25_dev.attr.page_size-(addr%w25_dev.attr.page_size); //单页剩余的字节数 if(len <= pageremain) pageremain = len;//不大于256个字节 while(1) { if(w25qxx_write_page(addr, buf, pageremain)) { return 1; } if(len == pageremain)break;//写入结束了 else //NumByteToWrite>pageremain { buf += pageremain; addr += pageremain; len -= pageremain; //减去已经写入了的字节数 if(len > 256)pageremain=256; //一次可以写入256个字节 else pageremain = len; //不够256个字节了 } } return 0; }
static uint8_t w25qxx_read_sr(void) { uint8_t buf[1]; buf[0] = W25X_ReadStatusReg; spi_write(&device, buf, 1, false); //false = 保持片选,继续发送 spi_read(&device, buf, 1, true); W25QXX_TRACE("W25QXX BUSY\r\n", buf[0]); return buf[0]; }
//向芯片写数据 int w25qxx_write(uint32_t addr, uint8_t *buf, uint32_t len) { uint32_t secpos; uint16_t secoff; uint16_t secremain; uint16_t i; uint8_t * mem_pool; mem_pool = SPI_FLASH_BUFFER; secpos = addr/4096;//扇区地址 secoff = addr%4096;//在扇区内的偏移 secremain = 4096-secoff;//扇区剩余空间大小 if(len <= secremain)secremain = len;//不大于4096个字节 while(1) { w25qxx_read(secpos*4096, mem_pool, 4096); //读出整个扇区的内容 for(i = 0; i < secremain; i++)//校验数据 { if(mem_pool[secoff+i]!=0XFF)break;//需要擦除 } if(i<secremain)//需要擦除 { w25qxx_erase_sector(secpos*4096); //擦除这个扇区 for(i=0;i<secremain;i++) //复制原来的数据 { mem_pool[i+secoff]=buf[i]; } w25qxx_write_no_check(secpos*4096, mem_pool,4096); //写入整个扇区 }else { W25QXX_TRACE("no need to erase -addr:%d\r\n", addr); w25qxx_write_no_check(addr, buf, secremain);//写已经擦除了的,直接写入扇区剩余区间. } if(len == secremain)break;//写入结束了 else//写入未结束 { secpos++;//扇区地址增1 secoff=0;//偏移位置为0 buf += secremain; //指针偏移 addr += secremain;//写地址偏移 len -= secremain; //字节数递减 if(len > 4096) secremain = 4096; //下一个扇区还是写不完 else secremain = len; //下一个扇区可以写完了 } } return SPI_EOK; }