📄 df.c
字号:
/*C**************************************************************************
* NAME: df.c
*----------------------------------------------------------------------------
* Copyright (c) 2006 Atmel.
*----------------------------------------------------------------------------
* RELEASE: at90usb128-usbkey-demo-3enum-host-mouse-1_0_4
* REVISION: 1.12
*----------------------------------------------------------------------------
* PURPOSE:
* This file contains the low-level dataflash routines
*
* NOTES:
* Global Variables:
* - gl_ptr_mem: long in data space
*****************************************************************************/
/*_____ I N C L U D E S ____________________________________________________*/
#include "config.h" /* system configuration */
#ifdef DF_VALIDATION
#include "virtual_usb.h"
#else
#include "lib_mcu\usb\usb_drv.h" /* usb driver definition */
#endif
#include "lib_mcu\spi\spi_drv.h" /* spi driver definition */
#include "df.h" /* dataflash definition */
/*_____ M A C R O S ________________________________________________________*/
/*_____ D E F I N I T I O N ________________________________________________*/
extern data Uint32 gl_ptr_mem; /* memory data pointer */
static U8 df_mem_busy; /* memories in busy state */
static U8 df_select; /* current memory selected */
/*_____ D E C L A R A T I O N ______________________________________________*/
static void df_wait_busy(void);
static void df_chipselect_current(void);
code s_format df_tab_format[]=
{
/* nb_cylinder, nb_head, nb_sector, nb_hidden, nb_sector_per_cluster */
{ (Uint16)255, (Byte)4, (Byte)8, (Byte)15, (Byte)8 }, /* DF_SIZE_4MB */
{ (Uint16)510, (Byte)4, (Byte)8, (Byte)15, (Byte)8 }, /* DF_SIZE_8MB */
{ (Uint16)510, (Byte)4, (Byte)16, (Byte)15, (Byte)8 }, /* DF_SIZE_16MB */
{ (Uint16)510, (Byte)8, (Byte)16, (Byte)15, (Byte)8 }, /* DF_SIZE_32MB */
};
#ifdef DF_4_MB /* AT45DB321 memories */
#if(DF_NB_MEM == 4)
xdata Uint32 DF_DISK_SIZE = DF_SIZE_16MB;
#elif (DF_NB_MEM == 2)
xdata Uint32 DF_DISK_SIZE = DF_SIZE_8MB;
#elif (DF_NB_MEM ==1)
xdata Uint32 DF_DISK_SIZE = DF_SIZE_4MB;
#endif
#endif
#ifdef DF_8_MB /* AT45DB642 memories */
#if(DF_NB_MEM == 4)
xdata Uint32 DF_DISK_SIZE = DF_SIZE_32MB;
#elif (DF_NB_MEM == 2)
xdata Uint32 DF_DISK_SIZE = DF_SIZE_16MB;
#elif (DF_NB_MEM ==1)
xdata Uint32 DF_DISK_SIZE = DF_SIZE_8MB;
#endif
#endif
//!
//! @brief This function initializes the SPI communication link between the DF and the DF driver.
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param none
//!
//! @return none
//!
//!/
static void df_spi_init(void)
{
Spi_set_mode(SPI_MASTER_MODE_3);
//Spi_set_rate(SPI_RATE_0); //impossible in AVR mode in spi_drv.h
Spi_config_speed(SPI_RATE_1); //theses 2 lines replace the Spi_set_rate(SPI_RATE_0)
Spi_set_doublespeed(); //theses 2 lines replace the Spi_set_rate(SPI_RATE_0)
// Spi_set_rate(SPI_RATE_0) -> SCK freq == fosc/2.
// ==
// Spi_config_speed(SPI_RATE_1) -> SCK freq == fosc/4
// +
// Spi_set_doublespeed() -> SCK freq == fosc/2
Spi_disable_ss();
Spi_enable();
}
//!
//! @brief This function initializes the Dataflash controller & the SPI bus(over which the DF is controlled).
//!
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param none
//!
//! @return bit
//! The memory is ready -> OK (always)
//!/
bit df_init (void)
{
// Init the SPI communication link between the DF and the DF driver.
df_spi_init();
// Data Flash Controller init.
df_mem_busy = 0; // all memories ready
df_select = MEM_DF0;
return(OK);
}
//!
//! @brief This function selects a DF memory according to the sector pointer
//! The "df_select" variable contains the current memory addressed
//! Refer to the documentation of the function df_translate_addr() for more information about zones management
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param memzone LSB of logical sector address to open
//!
//! @return none
//!/
static void df_chipselect_memzone(U8 memzone)
{
#if (DF_NB_MEM == 1)
df_select = MEM_DF0;
#else
#if (DF_NB_MEM == 2)
#if (DF_PAGE_SIZE == 512)
if ((memzone&0x01) == 0) // each page parity matches a memory
df_select = MEM_DF0;
else
df_select = MEM_DF1;
#else
if ((memzone&0x02) == 0) // each double page parity matches a memory
df_select = MEM_DF0;
else
df_select = MEM_DF1;
#endif
#else
#if (DF_PAGE_SIZE == 512)
switch(memzone&0x3)
{
case 0:
df_select = MEM_DF0;
break;
case 1:
df_select = MEM_DF1;
break;
case 2:
df_select = MEM_DF2;
break;
case 3:
df_select = MEM_DF3;
break;
default:
break;
}
#else
switch((memzone>>1)&0x3)
{
case 0:
df_select = MEM_DF0;
break;
case 1:
df_select = MEM_DF1;
break;
case 2:
df_select = MEM_DF2;
break;
case 3:
df_select = MEM_DF3;
break;
default:
break;
}
#endif
#endif
#endif
}
//!
//! @brief This function physically selects the current addressed memory
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param none
//!
//! @return none
//!/
static void df_chipselect_current(void)
{
Df_desel_all();
#ifndef AVRGCC
#if (DF_NB_MEM == 1)
Df_select_df(0,DF_SELECT_MEM);
#else
#if (DF_NB_MEM == 2)
if (df_select == MEM_DF0)
Df_select_df(0,DF_SELECT_MEM);
else
Df_select_df(1,DF_SELECT_MEM);
#else
switch (df_select)
{
case MEM_DF0:
Df_select_df(0,DF_SELECT_MEM);
break;
case MEM_DF1:
Df_select_df(1,DF_SELECT_MEM);
break;
case MEM_DF2:
Df_select_df(2,DF_SELECT_MEM);
break;
default:
Df_select_df(3,DF_SELECT_MEM);
break;
}
#endif
#endif
#else // FOR AVRGCC...
#if (DF_NB_MEM == 1)
DF_CS_PORT &= (U8)(~(1<<DF_CS0));
#else
#if (DF_NB_MEM == 2)
if (df_select == MEM_DF0)
DF_CS_PORT &= (U8)(~(1<<DF_CS0));
else
DF_CS_PORT &= (U8)(~(1<<DF_CS1));
#else
switch (df_select)
{
case MEM_DF0:
DF_CS_PORT &= (U8)(~(1<<DF_CS0));
break;
case MEM_DF1:
DF_CS_PORT &= (U8)(~(1<<DF_CS1));
break;
case MEM_DF2:
DF_CS_PORT &= (U8)(~(1<<DF_CS2));
break;
default:
DF_CS_PORT &= (U8)(~(1<<DF_CS3));
break;
}
#endif
#endif
#endif
}
//!
//! @brief This function translates the logical sector address to the physical byte address (1 logical sector = 512 bytes)
//! In function of the memory configuration (number 1x/2x/4x, pages 512b/1024b) :
//!
//! MEMORIES WITH PAGES OF 512 BYTES :
//! ==================================
//! Consider the logical sector address as "xx..xxba", where 'b' and 'a' are the two last bits, and "xx..xx" an undefined number of more significant bits
//! - If 1 memory is used, this logical sector address directly matches with the physical sector address
//! So the physical sector address is "xx..xxba"
//! - If 2 memories are used, the bit 'a' indicates the memory concerned, and the rest of the address indicates the physical address
//! So the physical sector address is "xx...xxb"
//! - If 4 memories are used, the bits 'ba' indicates the memory concerned, and the rest of the address indicates the physical address
//! So the physical sector address is "xx....xx"
//!
//! MEMORIES WITH PAGES OF 1024 BYTES :
//! ==================================
//! Consider the logical sector address as "xx..xxcba", where 'c', 'b' and 'a' are the three last bits, and "xx..xx" an undefined number of more significant bits
//! - If 1 memory is used, this logical sector address directly matches with the physical sector address
//! So the physical sector address is "xx..xxcba"
//! - If 2 memories are used, the bit 'b' indicates the memory concerned, and the rest of the address indicates the physical address
//! So the physical sector address is "xx...xxca"
//! - If 4 memories are used, the bits 'cb' indicates the memory concerned, and the rest of the address indicates the physical address
//! So the physical sector address is "xx....xxa"
//!
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param log_sect_addr logical sector address
//!
//! @return U32 physical byte address
//!/
static U32 df_translate_addr(Uint32 log_sect_addr)
{
#if (DF_NB_MEM == 1)
return (log_sect_addr << 9); // this case if only one memory...
#else
#if (DF_NB_MEM == 2)
#if (DF_PAGE_SIZE == 512)
return ((log_sect_addr&0xFFFFFFFE) << 8);
#else
return (((log_sect_addr&0xFFFFFFFC) << 8) | ((log_sect_addr&0x00000001) << 9));
#endif
#else
#if (DF_PAGE_SIZE == 512)
return ((log_sect_addr&0xFFFFFFFC) << 7);
#else
return (((log_sect_addr&0xFFFFFFF8) << 7) | ((log_sect_addr&0x00000001) << 9));
#endif
#endif
#endif
}
//!
//! @brief This function performs a memory check on all DF.
//!
//!
//! @warning Code:?? bytes (function code length)
//!
//! @param none
//!
//! @return bit
//! The memory is ready -> OK
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -