/*! \file spiflash.c \brief SPI Flash Memory Driver (M25Pxx/AT25Fxxx/etc). */
//*****************************************************************************
//
// File Name : 'spiflash.c'
// Title : SPI Flash Memory Driver (M25Pxx/AT25Fxxx/etc)
// Author : Pascal Stang - Copyright (C) 2006
// Created : 2006-04-15
// Revised : 2006-07-02
// Version : 0.1
// Target MCU : AVR processors
// Editor Tabs : 4
//
// NOTE: This code is currently below version 1.0, and therefore is considered
// to be lacking in some functionality or documentation, or may not be fully
// tested. Nonetheless, you can expect most functions to work.
//
//*****************************************************************************
// system includes
#include "avr/io.h"
#include "global.h"
// library includes
#include "spi.h"
#include "spiflash.h"
#define SPIFLASH_CONFIG_CS DDRB |= (1<<0)
#define SPIFLASH_ASSERT_CS PORTB &= (1<<0)
#define SPIFLASH_RELEASE_CS PORTB |= (1<<0)
// functions
void spiflashInit(void)
{
// initialize spi
spiInit();
// initialize chip select
SPIFLASH_RELEASE_CS;
SPIFLASH_CONFIG_CS;
}
unsigned short spiflashGetID(void)
{
unsigned short id;
SPIFLASH_ASSERT_CS;
spiByte(0, SPIFLASH_CMD_RDID, 0);
id = spiByte(0, 0x00, 0)<<8;
id |= spiByte(0, 0x00, 1);
SPIFLASH_RELEASE_CS;
return id;
}
void spiflashChipErase(void)
{
// enable write
SPIFLASH_ASSERT_CS;
spiByte(0, SPIFLASH_CMD_WREN, 1);
SPIFLASH_RELEASE_CS;
// clock out dummy byte to waste time
spiByte(0, 0x00, 1);
// do chip erase
SPIFLASH_ASSERT_CS;
spiByte(0, SPIFLASH_CMD_CHIPERASE, 1);
SPIFLASH_RELEASE_CS;
// clock out dummy byte to waste time
spiByte(0, 0x00, 1);
// wait until write is done
SPIFLASH_ASSERT_CS;
spiByte(0, SPIFLASH_CMD_RDSR, 0);
while(spiByte(0, 0x00, 0) & SPIFLASH_STATUS_BUSY);
SPIFLASH_RELEASE_CS;
}
void spiflashRead(unsigned long addr, unsigned long nbytes, unsigned char *data)
{
// begin read
SPIFLASH_ASSERT_CS;
// issue read command
spiByte(0, SPIFLASH_CMD_READ, 0);
// send address
spiByte(0, addr>>16, 0);
spiByte(0, addr>>8, 0);
spiByte(0, addr>>0, 0);
// read data
while(nbytes--)
*data++ = spiByte(0, 0x00, 0);
// end read
SPIFLASH_RELEASE_CS;
}
void spiflashWrite(unsigned long addr, unsigned long nbytes, unsigned char *data)
{
unsigned int page;
unsigned int i;
unsigned int pagelen;
// loop through pages to be programmed
for(page=0; page<((nbytes+SPIFLASH_PAGESIZE-1)>>8); page++)
{
// program this page
// enable write
SPIFLASH_ASSERT_CS;
spiByte(0, SPIFLASH_CMD_WREN, 1);
SPIFLASH_RELEASE_CS;
// clock out dummy byte to waste time
spiByte(0, 0x00, 1);
// begin write
SPIFLASH_ASSERT_CS;
// issue write command
spiByte(0, SPIFLASH_CMD_PAGEPROG, 0);
// send address
spiByte(0, addr>>16, 0);
spiByte(0, addr>>8, 0);
spiByte(0, addr>>0, 0);
// program exactly the number of bytes requested
if( ((page<<8)+SPIFLASH_PAGESIZE) <= nbytes)
pagelen = SPIFLASH_PAGESIZE;
else
pagelen = nbytes-(page<<8);
// transfer data
for(i=0; i<pagelen; i++)
spiByte(0, *data++, 0);
// end write
SPIFLASH_RELEASE_CS;
// clock out dummy byte to waste time
spiByte(0, 0x00, 1);
// wait until write is done
SPIFLASH_ASSERT_CS;
spiByte(0, SPIFLASH_CMD_RDSR, 0);
while(spiByte(0, 0x00, 0) & SPIFLASH_STATUS_BUSY);
SPIFLASH_RELEASE_CS;
// clock out dummy byte to waste time
spiByte(0, 0x00, 1);
}
}
|