Main Page | Modules | Related Pages | Examples

df/module-src/dflash.c

/*
 * Turbo Programmer Utilities, turbo-prog-utils, www.bladox.com 
 *
 * Copyright (C) 2004 BLADOX, s.r.o.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#include <config.h>
#include <tprog/tprog.h>

#include <avr/io.h>
#include <avr/interrupt.h>

#include "dflash.h"

#define MMC_CS_DDR              DDRD
#define MMC_CS_DDR_DD           DD7
#define MMC_CS_PORT             PORTD
#define MMC_CS_PORT_PIN         PORT7

u8 df_id;
u16 df_pages;
u8 df_blocks;
u8 df_off;

void delayOneUs ()
{
  delayUs (1);
}

u8 dataFlashInit ()
{
  u8 i;

  i = dataFlashStatusRegisterRead ();
  if (i == 0xFF)
  {
    df_id = 0xFF;
    df_pages = 0x0000;
    df_blocks = 0x00;
    df_off = 0x00;
    return 0xFF;
  }
  i &= 0x3C;

  switch (i)
  {
    case DEV_AT45DB161B:
      df_id = DEV_AT45DB161B;
      df_pages = 4096;
      df_blocks = 2;
      df_off = 2;
      break;
    case DEV_AT45DB321B:
      df_id = DEV_AT45DB321B;
      df_pages = 8192;
      df_blocks = 2;
      df_off = 2;
      break;
    case DEV_AT45DB642B:
      df_id = DEV_AT45DB642B;
      df_pages = 8192;
      df_blocks = 4;
      df_off = 3;
      break;
    default:
      df_id = DEV_UNKNOWN;
      df_pages = 512;
      df_blocks = 1;
      df_off = 1;
      break;
  }
  return 0x00;
}

//-------------------------------------------------
// DataFlash Status Register Read
//-------------------------------------------------
u8 dataFlashStatusRegisterRead ()
{
  u8 retValue;
  u8 rxValue;
  u8 interrupts;

  //store global interrupt enable bit
  interrupts = (inb (SREG) & (1 << SREG_I));
  cli ();

  cbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  // send command to DataFlash SPI bus
  outb (SPDR, 0xD7);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, 0x00);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  retValue = inb (SPDR);

  delayOneUs ();

  //disable DataFlash 
  //set FCSn to log.1
  sbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  //restore global interrupt enable bit
  if (interrupts != 0)
    sei ();

  return retValue;
}

//-------------------------------------------------
// DataFlash Page Erase
// Erases one page from DataFlash Memory
//-------------------------------------------------
u8 dataFlashPageErase (u16 pageAddr)
{
  u8 retValue;
  u8 rxValue;
  u8 commandValue;
  u8 interrupts;

  while ((dataFlashStatusRegisterRead () & 0x80) == 0);

  retValue = 0;

  commandValue = 0x81;

  //store global interrupt enable bit
  interrupts = (inb (SREG) & (1 << SREG_I));
  cli ();

  //enable DataFlash 
  //set FCSn to log.0
  cbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  // send command to DataFlash SPI bus
  outb (SPDR, commandValue);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send page address to DataFlash SPI bus
  outb (SPDR, (pageAddr >> (8 - df_off)));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send page address to DataFlash SPI bus
  //outb(SPDR,((pageAddr & 0x7F) << 1));
  outb (SPDR, pageAddr << df_off);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, 0x00);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  delayOneUs ();

  //disable DataFlash 
  //set FCSn to log.1
  sbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  //restore global interrupt enable bit
  if (interrupts != 0)
    sei ();

  return retValue;
}

//-------------------------------------------------
// DataFlash Block Erase
// Erases 8 pages from DataFlash Memory
//-------------------------------------------------
u8 dataFlashBlockErase (u16 blockAddr)
{
  u8 retValue;
  u8 rxValue;
  u8 commandValue;
  u8 interrupts;

  retValue = 0;

  commandValue = 0x50;

  //store global interrupt enable bit
  interrupts = (inb (SREG) & (1 << SREG_I));
  cli ();

  //enable DataFlash 
  //set FCSn to log.0
  cbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  // send command to DataFlash SPI bus
  outb (SPDR, commandValue);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send page address to DataFlash SPI bus
  outb (SPDR, (blockAddr >> 4));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send start page address of block to DataFlash SPI bus 
  outb (SPDR, ((blockAddr & 0x0F) << 4));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, 0x00);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  delayOneUs ();

  //disable DataFlash 
  //set FCSn to log.1
  sbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  //restore global interrupt enable bit
  if (interrupts != 0)
    sei ();

  return retValue;
}

//-------------------------------------------------
// DataFlash Buffer Read
// if bufferNumber = 0 - left buffer access
// if bufferNumber != 0 - right buffer access
// reads from one of buffers in dataFlash 
// to "buffer" from "addr" position "size" bytes
//-------------------------------------------------
u8 dataFlashBufferRead (u8 bufferNumber, u8 * buffer, u16 addr, u16 size)
{
  unsigned char retValue;
  unsigned char rxValue;
  unsigned char commandValue;
  unsigned int i;
  u8 interrupts;

  retValue = 0;

  commandValue = 0xD4;
  if (bufferNumber != 0)
    commandValue = 0xD6;

  //store global interrupt enable bit
  interrupts = (inb (SREG) & (1 << SREG_I));
  cli ();

  //enable DataFlash 
  //set FCSn to log.0
  cbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  // send command to DataFlash SPI bus
  outb (SPDR, commandValue);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, 0x00);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, (addr >> 8));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, (addr & 0xFF));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, 0x00);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  for (i = 0; i < size; i++)
  {
    // send dumb data to DataFlash SPI bus
    outb (SPDR, 0x00);
    // wait until char was transmitted
    loop_until_bit_is_set (SPSR, SPIF);
    buffer[i] = inb (SPDR);
  }

  delayOneUs ();

  //disable DataFlash 
  //set FCSn to log.1
  sbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  //restore global interrupt enable bit
  if (interrupts != 0)
    sei ();

  return retValue;
}

//-------------------------------------------------
// DataFlash Memory to Buffer Read
// if bufferNumber = 0 - left buffer access
// if bufferNumber != 0 - right buffer access
// reads one page from DataFlash Memory
// to one of buffers in dataFlash 
//-------------------------------------------------
u8 dataFlashMemoryToBufferRead (u8 bufferNumber, u16 pageAddr)
{
  u8 retValue;
  u8 rxValue;
  u8 commandValue;
  u8 interrupts;

  while ((dataFlashStatusRegisterRead () & 0x80) == 0);
  retValue = 0;

  commandValue = 0x53;
  if (bufferNumber != 0)
    commandValue = 0x55;

  //store global interrupt enable bit
  interrupts = (inb (SREG) & (1 << SREG_I));
  cli ();

  //enable DataFlash 
  //set FCSn to log.0
  cbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  // send command to DataFlash SPI bus
  outb (SPDR, commandValue);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send page address to DataFlash SPI bus
  outb (SPDR, (pageAddr >> (8 - df_off)));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send page address to DataFlash SPI bus
  outb (SPDR, pageAddr << df_off);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, 0x00);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  delayOneUs ();

  //disable DataFlash 
  //set FCSn to log.1
  sbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  //restore global interrupt enable bit
  if (interrupts != 0)
    sei ();

  while ((dataFlashStatusRegisterRead () & 0x80) == 0);

  return retValue;
}

//-------------------------------------------------
// DataFlash Buffer Write
// if bufferNumber = 0 - left buffer access
// if bufferNumber != 0 - right buffer access
// writes to one of buffers in dataFlash 
// from "buffer" from "addr" position "size" bytes
//-------------------------------------------------
u8 dataFlashBufferWrite (u8 bufferNumber, u8 * buffer, u16 addr, u16 size)
{
  u8 retValue;
  u8 rxValue;
  u8 commandValue;
  u16 i;
  u8 interrupts;

  retValue = 0;

  commandValue = 0x84;
  if (bufferNumber != 0)
    commandValue = 0x87;

  //store global interrupt enable bit
  interrupts = (inb (SREG) & (1 << SREG_I));
  cli ();

  //enable DataFlash 
  //set FCSn to log.0
  cbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  // send command to DataFlash SPI bus
  outb (SPDR, commandValue);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, 0x00);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, (addr >> 8));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, (addr & 0xFF));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  for (i = 0; i < size; i++)
  {
    // send buffer data to DataFlash SPI bus
    outb (SPDR, buffer[i]);
    // wait until char was transmitted
    loop_until_bit_is_set (SPSR, SPIF);
    rxValue = inb (SPDR);
  }

  delayOneUs ();

  //disable DataFlash 
  //set FCSn to log.1
  sbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  //restore global interrupt enable bit
  if (interrupts != 0)
    sei ();

  return retValue;
}

//-------------------------------------------------
// DataFlash Buffer To Memory Program With Erase
// if bufferNumber = 0 - left buffer access
// if bufferNumber != 0 - right buffer access
// writes to one of buffers into dataFlash memory
// to page at "pageAddr"
//-------------------------------------------------
u8 dataFlashBufferToMemoryProgramWithErase (u8 bufferNumber, u16 pageAddr)
{
  u8 retValue;
  u8 rxValue;
  u8 commandValue;
  u8 interrupts;

  while ((dataFlashStatusRegisterRead () & 0x80) == 0);
  retValue = 0;

  commandValue = 0x83;
  if (bufferNumber != 0)
    commandValue = 0x86;

  //store global interrupt enable bit
  interrupts = (inb (SREG) & (1 << SREG_I));
  cli ();

  //enable DataFlash 
  //set FCSn to log.0
  cbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  // send command to DataFlash SPI bus
  outb (SPDR, commandValue);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send page address to DataFlash SPI bus
  outb (SPDR, (pageAddr >> (8 - df_off)));

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send page address to DataFlash SPI bus
  outb (SPDR, pageAddr << df_off);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  // send dumb data to DataFlash SPI bus
  outb (SPDR, 0x00);

  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  rxValue = inb (SPDR);

  delayOneUs ();

  //disable DataFlash 
  //set FCSn to log.1
  sbi (MMC_CS_PORT, MMC_CS_PORT_PIN);

  delayOneUs ();

  //restore global interrupt enable bit
  if (interrupts != 0)
    sei ();

  while ((dataFlashStatusRegisterRead () & 0x80) == 0);

  return retValue;
}


Copyright © 2004 BLADOX
Turbo Programmer version 2.0