PIC Micro Controller C Input / Output Routine

SPI to Atmel 45Dxx series of data flash

Michail Evstafiev [Evstaf at LUMEX.RU] says:

These routines for Atmel 45Dxx series of data flash and software SPI master. I am using Hi-Tech C. You must define some macro for chip select and others.
//ATMEL SerialDataFlash Commands
#define MAIN_MEMORY_PAGE_READ                    0x52
#define BUFFER1_READ                             0x54
#define BUFFER2_READ                             0x56
#define MAIN_MEMORY_PAGE_TO_BUFFER1_COPY         0x53
#define MAIN_MEMORY_PAGE_TO_BUFFER2_COPY         0x55
#define MAIN_MEMORY_PAGE_TO_BUFFER1_COMPARE      0x60
#define MAIN_MEMORY_PAGE_TO_BUFFER2_COMPARE      0x61
#define BUFFER1_WRITE                            0x84
#define BUFFER2_WRITE                            0x87
#define BUFFER1_PROGRAM_WITH_ERASE               0x83
#define BUFFER2_PROGRAM_WITH_ERASE               0x86
#define BUFFER1_PROGRAM_NO_ERASE                 0x88
#define BUFFER2_PROGRAM_NO_ERASE                 0x89
#define PAGE_ERASE                               0x81
#define BLOCK_ERASE                              0x50
#define MAIN_MEMORY_THROUGH_BUFFER1_PROGRAM      0x82
#define MAIN_MEMORY_THROUGH_BUFFER2_PROGRAM      0x85
#define AUTO_PAGE_THROUGH_BUFFER1_REWRITE        0x58
#define AUTO_PAGE_THROUGH_BUFFER2_REWRITE        0x59
#define DATA_FLASH_STATUS                        0x57

#define DATA_FLASH_BUFFER1 0x00
#define DATA_FLASH_BUFFER2 0x01

//polarity of ready/busy signaling
#define IS_DATA_FLASH_BUSY() IS_DATA_FLASH_READY_LO()

//DataFlash status register bits
#define DATA_FLASH_STATUS_READY_MASK   0x80
#define IS_DATA_FLASH_READY(_status_)      (_status_ &                      \
                                            DATA_FLASH_STATUS_READY_MASK)
#define DATA_FLASH_STATUS_COMPARE_MASK 0x40
#define IS_DATA_FLASH_COMPARE_OK(_status_) ((_status_ &                     \
                                            DATA_FLASH_STATUS_COMPARE_MASK) \
                                            == 0)
#define DATA_FLASH_STATUS_DENSITY_MASK 0x34
#define DATA_FLASH_32MBIT_DESITY_CODE  0x30

//Density related parameters
#define MAX_PAGE_32MBIT_DENSITY    8192

//write byte to SPI (mode 3) as a master
void wrSPI(char Shift)
{
   register BYTE BitCnt = 8;
   do
   {
      SPI_SCK_LO();
      if(Shift & 0x80)
         SPI_SDO_HI();
      else
         SPI_SDO_LO();
      Shift <<= 1;
      SPI_SCK_HI();
   } while (--BitCnt);
}

//read byte from SPI (mode 3) as a master
BYTE rdSPI(void)
{
   register BYTE BitCnt = 8;
   register BYTE Shift;
   do
   {
      SPI_SCK_LO();
      Shift <<= 1;
      if(IS_SPI_SDI_LO())
         Shift &= ~1;
      else
         Shift |= 1;
      SPI_SCK_HI();
   } while (--BitCnt);
   return(Shift);
}

BYTE ReadDataFlashStatus(void)
{
   BYTE Data;

   DATA_FLASH_CS_LO();

   //command
   wrSPI(DATA_FLASH_STATUS);

   Data = rdSPI();

   DATA_FLASH_CS_HI();

   return (Data);
}

void WriteByteToDataFlashBuffer1(UINT16 Address, BYTE Data)
{
   DATA_FLASH_CS_LO();

   //command
   wrSPI(BUFFER1_WRITE);
   //don't care 8 bits
   wrSPI(0);
   //2 high address bits
   wrSPI(*((BYTE*)&Address +1));
   //8 low address bits
   wrSPI((BYTE)Address);
   //write data byte
   wrSPI(Data);

   DATA_FLASH_CS_HI();
}

BYTE ReadByteFromDataFlashBuffer1(UINT16 Address)
{
   BYTE Data;

   DATA_FLASH_CS_LO();

   //command
   wrSPI(BUFFER1_READ);
   //don't care 8 bits
   wrSPI(0);
   //2 high address bits
   wrSPI(*((BYTE*)&Address +1));
   //8 low address bits
   wrSPI((BYTE)Address);
   //don't care 8 bits
   wrSPI(0);

   Data = rdSPI();

   DATA_FLASH_CS_HI();

   return (Data);
}

void EraseDataFlashPage(UINT16 PageNum)
{
   DATA_FLASH_CS_LO();

   PageNum <<= 2;

   //command
   wrSPI(PAGE_ERASE);
   //7 high address bits
   wrSPI(*((BYTE*)&PageNum + 1));
   //6 low address bits
   wrSPI((BYTE)PageNum);
   //don't care 8 bits
   wrSPI(0);

   DATA_FLASH_CS_HI();
}

BYTE ReadByteFromMainMemory(UINT16 PageNum, UINT16 SubAddress)
{
   BYTE Data;

   PageNum <<= 2;

   DATA_FLASH_CS_LO();

   //command
   wrSPI(MAIN_MEMORY_PAGE_READ);
   //7 high page numder bits
   wrSPI(*((BYTE*)&PageNum +1));
   //6 low page number bits and 2 high address bits
   wrSPI(((BYTE)PageNum & 0b11111100) | (*((BYTE*)&SubAddress +1) & 0b11));
   //8 low address bits
   wrSPI((BYTE)SubAddress);
   //don't care 32 bits
   wrSPI(0);
   wrSPI(0);
   wrSPI(0);
   wrSPI(0);

   Data = rdSPI();

   DATA_FLASH_CS_HI();

   return (Data);
}

void ProgramBuffer1ToDataFlashMainMemory(UINT16 PageNum)
{
   PageNum <<= 2;

   DATA_FLASH_CS_LO();

   //command
   wrSPI(BUFFER1_PROGRAM_NO_ERASE);
   //7 high address bits
   wrSPI(*((BYTE*)&PageNum + 1));
   //6 low address bits
   wrSPI((BYTE)PageNum);
   //don't care 8 bits
   wrSPI(0);

   DATA_FLASH_CS_HI();
}

Interested:

Questions: