📄 am29xxxx.c
字号:
/*
* File: src/dev/flash/am29xxxx.c
* Purpose: Firmware Flash API driver for AM29XXXX Flash.
*
* Notes: This driver supports a single type (AM29XXXX) and
* width of FLASH. The type and width support is done
* at compilation. It supports multiple banks of same-
* width Flash, as well as consecutive/contiguous banks.
*
*/
#include "src/include/dbug.h"
#include "src/dev/flash/am29xxxx.h"
/********************************************************************/
/*
* If AM29XXXX_EXTRA_INCLUDE is defined, then include the
* appropriate file. This is a method for including other
* types/definitions without modifying this file.
*/
#ifdef AM29XXXX_EXTRA_INCLUDE
#define AM29XXXX_XINCLUDE
#include AM29XXXX_EXTRA_INCLUDE
#undef AM29XXXX_XINCLUDE
#endif
/********************************************************************/
/*
* The AMD29F010 FLASH devices. These devices are 128K x 8.
* The AMD29F040 FLASH devices. These devices are 512K x 8.
* The AMD29F080 FLASH devices. These devices are 1024K x 8.
* The AMD29F016 FLASH devices. These devices are 2048K x 8.
* The AMD29LV004 FLASH devices. These devices are 512K x 8.
* The AMD29PL160 FLASH devices. These devices are 2048K x 8.
*
* Note: This driver supports one of the following configurations
* for these devices. Possible configurations are:
*
* 1 AMD29F0XX as a single 8-bit memory device
* 2 AMD29F0XXs as a single 16-bit memory device
* 4 AMD29F0XXs as a single 32-bit memory device
* 1 AMD29F800 as a single 8-bit memory device
* 2 AMD29F800s as a single 32-bit memory device
* 2 AMD29LV004s as a single 16-bit memory device
* 1 AMD29PL160 as a single 16-bit memory device
*
* One of the following C pre-processor define statements must
* exist at compilation time:
*
* #define AM29XXXX_8BIT
* #define AM29XXXX_16BIT
* #define AM29XXXX_32BIT
*
* One of the following C pre-processor define statements must
* exist at compilation time:
*
* #define AM29XXXX_AM29F010
* #define AM29XXXX_AM29F040
* #define AM29XXXX_AM29F080
* #define AM29XXXX_AM29F016
* #define AM29XXXX_AM29F800B
* #define AM29XXXX_AM29F800T
* #define AM29XXXX_AM29LV004BB
* #define AM29XXXX_AM29LV004BT
* #define AM29XXXX_AM29PL160CB8
* #define AM29XXXX_AM29PL160CT8
* #define AM29XXXX_AM29PL160CB16
* #define AM29XXXX_AM29PL160CT16
*
* IMPORTANT: It is not possible to execute any of these routines
* if the code for these routines is in the FLASH itself. This is
* because these routines change the mode of the device so that reads
* from it are not always possible. The code must be executed out of
* RAM.
*/
/*
* WARNING: To eliminate playing alot of games with the linker
* to properly treat this PIC driver, the two routines/symbols
* AM29XXXX_start and AM29XXXX_end are used to determine the
* start and end of the FLASH PIC driver in ROM/FLASH so that it
* can be copied out to RAM and then executed. In other words,
* any modifications/additions must be between these two functions!
*/
/********************************************************************/
void
am29xxxx_start (void)
{
}
/********************************************************************/
/*
* If AM29XXXX_EXTRA_CODE is defined, then include the
* appropriate file. This is a method for including other
* code without modifying this file. Keep in mind that all
* code will need to be self contained!!!
*/
#ifdef AM29XXXX_EXTRA_CODE
#define AM29XXXX_XCODE
#include AM29XXXX_EXTRA_CODE
#undef AM29XXXX_XCODE
#endif
/********************************************************************/
int
am29xxxx_write(AM29XXXX *AM29XXXX_PT,
FLASH *fwflash,
void (*func)(void),
void (*putchar)(int))
{
int blockindex, blocksz, index, cellindex, sector_size;
int written,done,timeouts;
int hashi=1,hashj=0;
int hash[8];
AM29XXXX_CELL * source;
AM29XXXX_CELL rdata, temp, manuf,id;
hash[0]=8; /* Backspace BS*/
hash[1]=124;/* "|" */
hash[2]=47; /* "/" */
hash[3]=45; /* "-" */
hash[4]=92; /* "\" */
hash[5]=42; /* "*" */
hash[6]=32; /* space SP*/
hash[7]=10; /* line feed LF */
/*
* Step 1) Identify the flash as AM29XXXX.
*/
AM29XXXX_WR_CMD1_AUTOSELECT(AM29XXXX_PT);
AM29XXXX_WR_CMD2_AUTOSELECT(AM29XXXX_PT);
AM29XXXX_WR_CMD3_AUTOSELECT(AM29XXXX_PT);
manuf=0;
id=0;
manuf = AM29XXXX_RD_MANUF(AM29XXXX_PT);
id = AM29XXXX_RD_ID(AM29XXXX_PT);
AM29XXXX_WR_CMD1_READ(AM29XXXX_PT);
AM29XXXX_WR_CMD2_READ(AM29XXXX_PT);
AM29XXXX_WR_CMD3_READ(AM29XXXX_PT);
if ((manuf & 0x00FF) != (AM29XXXX_AMD_CODE & 0x00FF))
return -1;
if ((id & 0x00FF) != (AM29XXXX_DEVICE_CODE & 0x00FF))
return -2;
/*
* Step 2) Point to the beginning sector and data block.
*/
#ifdef AM29XXXX_VARIABLE_SECTOR
AM29XXXX_sector_index(fwflash->sect, cellindex);
#else
cellindex = fwflash->sect * AM29XXXX_SECTOR_SIZE;
#endif
blockindex = 0;
blocksz = 0;
source = (AM29XXXX_CELL *)fwflash->blockptr[0];
done = FALSE;
written = 0;
while (!done)
{
#ifdef AM29XXXX_VARIABLE_SECTOR
AM29XXXX_sector_size(fwflash->sect, sector_size);
#else
sector_size = AM29XXXX_SECTOR_SIZE;
#endif
/*
* Step 3) Erase the sector.
*/
AM29XXXX_WR_CMD1_SECTORERASE(AM29XXXX_PT);
AM29XXXX_WR_CMD2_SECTORERASE(AM29XXXX_PT);
AM29XXXX_WR_CMD3_SECTORERASE(AM29XXXX_PT);
AM29XXXX_WR_CMD4_SECTORERASE(AM29XXXX_PT);
AM29XXXX_WR_CMD5_SECTORERASE(AM29XXXX_PT);
AM29XXXX_WR_CELL(AM29XXXX_PT, cellindex, AM29XXXX_SECTORERASE_CMD6);
do temp = AM29XXXX_RD_CELL(AM29XXXX_PT, cellindex);
while ((temp & AM29XXXX_SECTORERASE_DONE) != AM29XXXX_SECTORERASE_DONE);
/*
* Step 4) Place device into read mode again
*/
AM29XXXX_WR_CMD1_READ(AM29XXXX_PT);
AM29XXXX_WR_CMD2_READ(AM29XXXX_PT);
AM29XXXX_WR_CMD3_READ(AM29XXXX_PT);
/*
* Step 5) Program the Flash with the data contained in RAM.
*/
for (index = 0; index < sector_size; ++index)
{
if (*source != AM29XXXX_port_value(0xFF))
{
if ((putchar != NULL))
{
/* Hash marks to indicate progress */
if (hashj == 1500)
{
hashj = -1;
putchar(hash[0]);
putchar(hash[hashi]);
hashi++;
if (hashi == 5)
{
hashi=1;
}
}
hashj++;
}
/*
* Perform the Byte Program command sequence.
*/
AM29XXXX_WR_CMD1_BYTEPROG(AM29XXXX_PT);
AM29XXXX_WR_CMD2_BYTEPROG(AM29XXXX_PT);
AM29XXXX_WR_CMD3_BYTEPROG(AM29XXXX_PT);
AM29XXXX_WR_CELL(AM29XXXX_PT, cellindex, *source);
/*
* Poll to make sure it is done before continuing...
*/
timeouts = 0;
while (TRUE)
{
rdata = AM29XXXX_RD_CELL(AM29XXXX_PT, cellindex);
if ((rdata & AM29XXXX_DATA_POLL_MASK) ==
(*source & AM29XXXX_DATA_POLL_MASK))
{
break;
}
else
{
rdata = AM29XXXX_RD_CELL(AM29XXXX_PT, cellindex);
if (rdata & AM29XXXX_TIME_EXCEEDED)
{
rdata = AM29XXXX_RD_CELL(AM29XXXX_PT, cellindex);
if ((rdata & AM29XXXX_DATA_POLL_MASK) ==
(*source & AM29XXXX_DATA_POLL_MASK))
{
break;
}
if (++timeouts > 1024)
{
break;
}
}
}
}
}
/*
* Verify write and increment bytes written counter.
*/
if (AM29XXXX_RD_CELL(AM29XXXX_PT, cellindex) == *source)
{
written += sizeof(AM29XXXX_CELL);
blocksz += sizeof(AM29XXXX_CELL);
++cellindex;
++source;
if (blocksz >= fwflash->blocksz)
{
blocksz = 0;
source = (AM29XXXX_CELL *)fwflash->blockptr[++blockindex];
if (blockindex >= fwflash->numblocks)
{
done = TRUE;
break;
}
}
if ((fwflash->blocksz != 0) && (written >= fwflash->blocksz))
{
if ((putchar != NULL))
{
putchar(hash[0]);
putchar(hash[5]);
putchar(hash[6]);
}
done = TRUE;
}
}
else
{
done = TRUE;
break;
}
}
if (++fwflash->sect >= AM29XXXX_SECTORS)
{
/* Place the device back in the read mode. */
AM29XXXX_WR_CMD1_READ(AM29XXXX_PT);
AM29XXXX_WR_CMD2_READ(AM29XXXX_PT);
AM29XXXX_WR_CMD3_READ(AM29XXXX_PT);
fwflash->sect = 0;
cellindex = 0;
AM29XXXX_PT += (AM29XXXX_sectors * AM29XXXX_SECTOR_SIZE);
/* done = TRUE; */
}
if ((putchar != NULL))
{
putchar(hash[0]);
putchar(hash[5]);
putchar(hash[6]);
}
}/*while(!done)*/
/* In the case that updbug is the caller, the address of the new ROM
* Monitor's entrance point is passed in and execution of the new Monitor
* begins
*/
if ((func != NULL))
{
putchar(hash[7]);
func();
}
return written;
}
/********************************************************************/
void
am29xxxx_end (void)
{
/*
* This function is empty and at the END of all code so that it
* can be used to compute the size of the code contained in this
* driver.
*/
}
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -