Strict Standards: Declaration of action_plugin_importoldchangelog::register() should be compatible with DokuWiki_Action_Plugin::register($controller) in /home/aqq20189/public_html/embedders.org/kurt/wiki/lib/plugins/importoldchangelog/action.php on line 8

Deprecated: Function split() is deprecated in /home/aqq20189/public_html/embedders.org/kurt/wiki/inc/auth.php on line 146

Warning: Cannot modify header information - headers already sent by (output started at /home/aqq20189/public_html/embedders.org/kurt/wiki/lib/plugins/importoldchangelog/action.php:8) in /home/aqq20189/public_html/embedders.org/kurt/wiki/inc/auth.php on line 236

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/aqq20189/public_html/embedders.org/kurt/wiki/inc/auth.php on line 390

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/aqq20189/public_html/embedders.org/kurt/wiki/inc/auth.php on line 390

Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /home/aqq20189/public_html/embedders.org/kurt/wiki/inc/auth.php on line 387

Strict Standards: Only variables should be passed by reference in /home/aqq20189/public_html/embedders.org/kurt/wiki/doku.php on line 69

Warning: Cannot modify header information - headers already sent by (output started at /home/aqq20189/public_html/embedders.org/kurt/wiki/lib/plugins/importoldchangelog/action.php:8) in /home/aqq20189/public_html/embedders.org/kurt/wiki/inc/actions.php on line 128
sources:at45db [embedders WiKi ]
Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /home/aqq20189/public_html/embedders.org/kurt/wiki/inc/template.php on line 222
 
/**
* @file	at45db.c
* @brief AT45DB Module
*
* Support Atmel AT45DB Flash Memory
*
* @author      Rustem Kalimullin
* @par E-mail:
*              hellos@mail.ru
* @par Copyright:
*              (c) Kurt, 2005
*/
 
#include "common.h"
#include "at45db.h"
#include "spi.h"
 
// Define DF_AUTODETECT_FEATURES to enable autodetect features
//#define DF_AUTODETECT_FEATURES
 
//! defines for all opcodes
enum {
	BLOCK_ERASE                      = 0x50, /**< erase 512 pages */
	MAIN_MEMORY_PAGE_READ            = 0x52, /**< main memory page read */
	MM_PAGE_TO_B1_XFER               = 0x53, /**< main memory page to buffer 1 transfer */
	BUFFER_1_READ                    = 0x54, /**< Buffer 1 read */
	MM_PAGE_TO_B2_XFER               = 0x55, /**< main memory page to buffer 2 transfer */
	BUFFER_2_READ                    = 0x56, /**< buffer 2 read */
	STATUS_REGISTER_READ             = 0x57, /**< status register */
	AUTO_PAGE_REWRITE_THROUGH_B1     = 0x58, /**< auto page rewrite through buffer 1 */
	AUTO_PAGE_REWRITE_THROUGH_B2     = 0x59, /**< auto page rewrite through buffer 2 */
	MM_PAGE_TO_B1_COMP               = 0x60, /**< main memory page compare to buffer 1 */
	MM_PAGE_TO_B2_COMP               = 0x61, /**< main memory page compare to buffer 2 */
	ARRAY_READ                       = 0x68, /**< start continuous array read */
	PAGE_ERASE                       = 0x81, /**< erase a 264 byte page */
	MM_PAGE_PROG_THROUGH_B1          = 0x82, /**< main memory page program through buffer 1 */
	B1_TO_MM_PAGE_PROG_WITH_ERASE    = 0x83, /**< buffer 1 to main memory page program with built-in erase */
	BUFFER_1_WRITE                   = 0x84, /**< Buffer 1 write */
	MM_PAGE_PROG_THROUGH_B2          = 0x85, /**< main memory page program through buffer 2 */
	B2_TO_MM_PAGE_PROG_WITH_ERASE    = 0x86, /**< buffer 2 to main memory page program with built-in erase */
	BUFFER_2_WRITE                   = 0x87, /**< buffer 2 write */
	B1_TO_MM_PAGE_PROG_WITHOUT_ERASE = 0x88, /**< buffer 1 to main memory page program without built-in erase */
	B2_TO_MM_PAGE_PROG_WITHOUT_ERASE = 0x89  /**< buffer 2 to main memory page program without built-in erase */
};
 
//! Error codes
enum { DF_NO_ERROR=0, DF_WAIT_FAIL, DF_NOT_MATCH, DF_UNKNOWN_DEVICE };
 
//! Last error
int df_last_error = DF_UNKNOWN_DEVICE;
 
//! Current position
__no_init unsigned long df_cur_pos;
 
////////////////////////////////////////////////////////////////////////////////
#if defined(DF_AUTODETECT_FEATURES)
 
//! Chip info structure
//! Supported chips
const struct stru_df_info {
	const char    *pszName;   //!< Name of chip
	unsigned int  pages;      //!< Number of pages
	unsigned int  page_size;  //!< Page size in bytes
	unsigned char page_bit;   //!< Page address len in bits
	unsigned char id_density; //!< Density ID mask
} df_table [] = {
	{ "AT45DB011B", 512,  264,  9,  (0x3<<2) }, // 1M
	{ "AT45DB021B", 1024, 264,  9,  (0x5<<2) }, // 2M
	{ "AT45DB041B", 2048, 264,  9,  (0x7<<2) }, // 4M
	{ "AT45DB081B", 4096, 264,  9,  (0x9<<2) }, // 8M
	{ "AT45DB161B", 4096, 528,  10, (0xB<<2) }, // 16M
	{ "AT45DB321B", 8192, 528,  10, (0xD<<2) }, // 32M
	{ "AT45DB642B", 8192, 1056, 11, (0xF<<2) }, // 64M
};
 
const char    *df_name      = "UNKNOWN";
unsigned char df_page_bits  = 9;
unsigned int  df_num_pages  = 4096;
unsigned int  df_page_size  = 264;
unsigned int  df_id_density = (0x9<<2);
unsigned long df_density    = 4096L*264L;
 
#else //////////////////////////////////////////////////////////////////////////
 
#define df_name       ("AT45DB081B")
#define df_num_pages  (4096)
#define df_page_size  (264)
#define df_page_bits  (9)
#define df_id_density (0x9<<2)
#define df_density    (4096L*264L)
 
#endif /////////////////////////////////////////////////////////////////////////
 
//---------------------------------------------------------
int at45db_getLastError( void )
{
	int err = df_last_error;
	df_last_error = DF_NO_ERROR;
	return err;
}
 
//---------------------------------------------------------
const char* at45db_getErrorString( int iErr )
{
	switch(iErr)
	{
	case DF_NO_ERROR:       return "No error";
	case DF_WAIT_FAIL:      return "Wait failed";
	case DF_NOT_MATCH:      return "Cfg failed";
	case DF_UNKNOWN_DEVICE: return "Unknown device";
	default:                return "Unknown error";
	}
}
 
//---------------------------------------------------------
void at45db_init_op( void )
{
	DATAFLASH_ENABLE();
	__no_operation();
}
 
//---------------------------------------------------------
void at45db_end_op( void )
{
	DATAFLASH_DISABLE();
	__no_operation();
}
 
//---------------------------------------------------------
void at45db_delay( void )
{
	unsigned char i=0x00;
	do { __no_operation(); } while (--i);
}
 
//---------------------------------------------------------
void at45db_reset(void)
{
	at45db_init_op();
	at45db_delay();
	DF_RESET_HI();
	at45db_delay();
	DF_RESET_LO();
	at45db_delay();
	at45db_end_op();
}
 
//---------------------------------------------------------
//! wait until DataFlash busy
void at45db_wait(void)
{
	unsigned int i;
	at45db_init_op();
	i =0x1FFF;
	do {
		spi_write(STATUS_REGISTER_READ);
		if( (spi_read() & (1<<7) ) != 0 ) break;
	} while( --i );
	df_last_error = (i != 0) ? DF_NO_ERROR : DF_WAIT_FAIL;
	at45db_end_op();
}
 
//---------------------------------------------------------
unsigned int _read_density_id(void)
{
	unsigned int id;
	at45db_init_op();
	spi_write(STATUS_REGISTER_READ);
	id = ( spi_read() & (0xF<<2) );
	at45db_end_op();
	return id;
}
 
//---------------------------------------------------------
int at45db_init(void)
{
	at45db_detect_error();
#if defined(DF_AUTODETECT_FEATURES)
	if ( df_last_error == DF_WAIT_FAIL ) return df_last_error;
 
	const struct stru_df_info *found = 0;
	df_id_density = _read_density_id();
	for( int i=0; i<(sizeof(df_table)/sizeof(df_table[0])); i++ ) {
		if( df_id_density == df_table[i].id_density ) {
			found = &df_table[i];
			break;
		}
	}
 
	if( !found ) {
		found = &df_table[0];
		df_last_error  = DF_UNKNOWN_DEVICE;
	}
 
	df_num_pages = found->pages;
	df_page_size = found->page_size;
	df_page_bits = found->page_bit;
	df_name      = found->pszName;
	df_density   = (long)df_num_pages * df_page_size;
#endif
	return df_last_error;
}
 
//---------------------------------------------------------
int at45db_detect_error(void)
{
	at45db_reset();
	at45db_wait();
	if( df_last_error == DF_NO_ERROR ) {
		if( _read_density_id() != df_id_density ) df_last_error = DF_NOT_MATCH;
	}
	return df_last_error;
}
 
//---------------------------------------------------------
void at45db_setpos(unsigned long pos) { df_cur_pos = pos; }
unsigned long at45db_getpos(void) { return df_cur_pos; }
 
//---------------------------------------------------------
const char*   at45db_getName(void)       { return df_name;      }
unsigned long at45db_getDensity ( void ) { return df_density;   }
unsigned int  at45db_getPageSize( void ) { return df_page_size; }
unsigned int  at45db_getNumPages( void ) { return df_num_pages; }
 
//---------------------------------------------------------
void at45db_start_read( void )
{	
	ldiv_t pos = ldiv(df_cur_pos, df_page_size);
	unsigned int cur_page = pos.quot, cur_ofs  = pos.rem;
 
	at45db_init_op();
	
	spi_write(ARRAY_READ);                                                       // Continuous Array Read op-code
	spi_write((unsigned char)(cur_page >> (16 - df_page_bits)));                 // upper part of page address
	spi_write((unsigned char)((cur_page << (df_page_bits - 8))+ (cur_ofs>>8)));  // lower part of page address and MSB of int.page adr.
	spi_write((unsigned char)(cur_ofs));                                         // LSB byte of internal page address
	spi_write(0x00);                                                             // perform 4 dummy writes
	spi_write(0x00);                                                             // in order to initiate DataFlash
	spi_write(0x00);                                                             // address pointers
	spi_write(0x00);
}
 
//---------------------------------------------------------
void at45db_cont_read(unsigned char *dst, unsigned int size)
{
	while( size-- ) {
		df_cur_pos++;
		*dst++ = spi_read();
	}
}
 
//---------------------------------------------------------
unsigned char at45db_cont_readbyte(void)
{
  df_cur_pos++;
  return spi_read();
}
 
//---------------------------------------------------------
void at45db_end_read( void )
{
	at45db_end_op();
}
 
//---------------------------------------------------------
unsigned int at45db_cont_verify(unsigned int size)
{
	unsigned int crc = 0xFFFF;
	do {
		df_cur_pos++;
		crc ^= spi_read();
		unsigned char k = 8;
		do {
			if (crc & 1)  { crc >>=1;  crc ^=0xA001; }
			else  { crc >>=1; }
		} while( --k );
	} while( --size );
	return crc;
}
 
//---------------------------------------------------------
void at45db_read( unsigned char *dst, unsigned int size )
{
	at45db_start_read();
	at45db_cont_read(dst, size);
	at45db_end_op();
}
 
//---------------------------------------------------------
void df_page_func( unsigned char cmd, unsigned int page )
{
	at45db_init_op();
	spi_write(cmd);
	spi_write((unsigned char)(page >> (16 - df_page_bits)));  // upper part of page address
	spi_write((unsigned char)(page << (df_page_bits - 8)));   // lower part of page address
	spi_write(0x00);                                          // don't cares
	at45db_end_op();
	at45db_wait();
}
 
//---------------------------------------------------------
void at45db_write( const unsigned char *src, unsigned int size )
{	
	while(size) {
	
		ldiv_t pos = ldiv( df_cur_pos, df_page_size );
		unsigned int cur_page = pos.quot, cur_ofs  = pos.rem;
		
		df_page_func(MM_PAGE_TO_B1_XFER, cur_page);
 
		at45db_init_op();
		spi_write(BUFFER_1_WRITE);                 // buffer 1 write op-code
		spi_write(0x00);                           // don't cares
		spi_write((unsigned char)(cur_ofs>>8));    // upper part of internal buffer address
		spi_write((unsigned char)(cur_ofs));       // lower part of internal buffer address
		do {
			spi_write(*src++);
			df_cur_pos++;
		} while( (--size) && (++cur_ofs < df_page_size) );
		at45db_end_op();
 
		df_page_func( B1_TO_MM_PAGE_PROG_WITH_ERASE, cur_page );
		df_page_func( AUTO_PAGE_REWRITE_THROUGH_B1,  cur_page );
	}
}
 
//---------------------------------------------------------
void at45db_start_write( void )
{
	ldiv_t pos = ldiv( df_cur_pos, df_page_size );
	unsigned int cur_page = pos.quot, cur_ofs  = pos.rem;
	at45db_end_op();
	df_page_func(MM_PAGE_TO_B1_XFER, cur_page );
	at45db_init_op();
	spi_write(BUFFER_1_WRITE);                 // buffer 1 write op-code
	spi_write(0x00);                           // don't cares
	spi_write((unsigned char)(cur_ofs>>8));    // upper part of internal buffer address
	spi_write((unsigned char)(cur_ofs));       // lower part of internal buffer address
 
}
 
//--------------------------------------------------------
void at45db_cont_write( unsigned char data )
{
	ldiv_t pos = ldiv( df_cur_pos, df_page_size );
	unsigned int cur_page = pos.quot, cur_ofs  = pos.rem;
	spi_write( data );
	df_cur_pos++;	
	if( cur_ofs == (df_page_size-1) ) {
		// internal buffer full. flush to nvram
		at45db_end_op();
		df_page_func( B1_TO_MM_PAGE_PROG_WITH_ERASE, cur_page );
		at45db_start_write();
	}
}
 
//--------------------------------------------------------
void at45db_end_write( void )
{
	at45db_end_op();
	ldiv_t pos = ldiv( df_cur_pos, df_page_size );
	unsigned int cur_page = pos.quot, cur_ofs  = pos.rem;
	if( cur_ofs ) {
		df_page_func( B1_TO_MM_PAGE_PROG_WITH_ERASE, cur_page );
	}
}
 
//---------------------------------------------------------
int at45db_erase(void)
{
	unsigned int i, err = 0;
	at45db_init();
	for( i=0; i<df_num_pages; i++ ) {
		df_page_func(PAGE_ERASE, i);
		if( df_last_error != DF_NO_ERROR ) err++;
	}
	return err;
}
 

Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /home/aqq20189/public_html/embedders.org/kurt/wiki/inc/template.php on line 738
sources/at45db.txt · Последние изменения: 2021/10/09 14:22 kurt
 

Strict Standards: Only variables should be passed by reference in /home/aqq20189/public_html/embedders.org/kurt/wiki/doku.php on line 77