am29xxxxx-instance.html
来自「ecos3.0 beta 的官方文档,html格式」· HTML 代码 · 共 1,368 行 · 第 1/3 页
HTML
1,368 行
><P
>All eCos flash device drivers must implement a standard interface,
defined by the generic flash code <CODE
CLASS="VARNAME"
>CYGPKG_IO_FLASH</CODE
>.
This interface includes a table of seven function pointers for various
operations: initialization, query, erase, program, read, locking and
unlocking. The query operation is optional and the generic flash
support provides a dummy implementation
<CODE
CLASS="FUNCTION"
>cyg_flash_devfn_query_nop</CODE
>. AM29xxxxx flash
devices are always directly accessible so there is no need for a
separate read function. The remaining functions are more complicated.
</P
><P
>Usually the table can be declared <TT
CLASS="LITERAL"
>const</TT
>. In a ROM
startup application this avoids both ROM and RAM copies of the table,
saving a small amount of memory. <TT
CLASS="LITERAL"
>const</TT
> should not
be used if the table may be modified by a platform-specific
initialization routine.
</P
><DIV
CLASS="REFSECT2"
><A
NAME="AM29XXXXX-INSTANCE-FUNCTIONS-INIT"
></A
><H3
>Initialization</H3
><P
>There is a choice of three main initialization functions. The simplest
is <CODE
CLASS="FUNCTION"
>cyg_flash_devfn_init_nop</CODE
>, which does nothing.
It can be used if the <CODE
CLASS="STRUCTNAME"
>cyg_am29xxxxx_dev</CODE
> and
<CODE
CLASS="STRUCTNAME"
>cyg_flash_dev</CODE
> structures are fully
initialized statically and the flash will just work without special
effort. This is useful if it is guaranteed that the board will always
be manufactured using the same flash chip, since the nop function
involves the smallest code size and run-time overheads.
</P
><P
>The next step up is
<CODE
CLASS="FUNCTION"
>cyg_am29xxxxx_init_check_devid_XX</CODE
>, where
<TT
CLASS="LITERAL"
>XX</TT
> will be replaced by the suffix appropriate for
the bus configuration. It is still necessary to provide all the device
information statically, including the <CODE
CLASS="STRUCTFIELD"
>devid</CODE
>
field in the <CODE
CLASS="STRUCTNAME"
>cyg_am29xxxxx_dev</CODE
> structure.
This initialization function will attempt to query the flash device
and check that the provided device id matches the actual hardware. If
there is a mismatch the device will be marked uninitialized and
subsequent attempts to manipulate the flash will fail.
</P
><P
>If the board may end up being manufactured with any of a number of
different flash chips then the driver can perform run-time
initialization, using a <CODE
CLASS="FUNCTION"
>cyg_am29xxxxx_init_cfi_XX</CODE
>
function. This queries the flash device as per the Common Flash Memory
Interface Specification, supported by all current devices (although
not necessarily by older devices). The
<CODE
CLASS="STRUCTFIELD"
>block_info</CODE
> field in the
<CODE
CLASS="STRUCTNAME"
>cyg_am29xxxxx_dev</CODE
> structure and the
<CODE
CLASS="STRUCTFIELD"
>end</CODE
> and
<CODE
CLASS="STRUCTFIELD"
>num_block_infos</CODE
> fields in the
<CODE
CLASS="STRUCTNAME"
>cyg_flash_dev</CODE
> structure will be filled in.
It is still necessary to supply the <CODE
CLASS="STRUCTFIELD"
>start</CODE
>
field statically since otherwise the driver will not know how to
access the flash device. The main disadvantage of using CFI is that it
increases the code size.
</P
><DIV
CLASS="CAUTION"
><P
></P
><TABLE
CLASS="CAUTION"
BORDER="1"
WIDTH="100%"
><TR
><TD
ALIGN="CENTER"
><B
>Caution</B
></TD
></TR
><TR
><TD
ALIGN="LEFT"
><P
>If CFI is used then the <CODE
CLASS="STRUCTNAME"
>cyg_am29xxxxx_dev</CODE
>
structure must not be declared <TT
CLASS="LITERAL"
>const</TT
>. The CFI code
will attempt to update the structure and will fail if the structure is
held in read-only memory. This would leave the flash driver
non-functional.
</P
></TD
></TR
></TABLE
></DIV
><P
>A final option is to use a platform-specific initialization function.
This may be useful if the board may be manufactured with one of a
small number of different flash devices and the platform HAL needs to
adapt to this. The AM29xxxxx driver provides a utility function to
read the device id, <CODE
CLASS="FUNCTION"
>cyg_am29xxxxx_read_devid_XX</CODE
>:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>static int
alaia_flash_init(struct cyg_flash_dev* dev)
{
int devid = cyg_am29xxxxx_read_devid_1616(dev);
switch(devid) {
case 0x0042 :
…
case 0x0084 :
…
default:
return CYG_FLASH_ERR_DRV_WRONG_PART;
}
}
</PRE
></TD
></TR
></TABLE
><P
>There are many other possible uses for a platform-specific
initialization function. For example initial prototype boards might
have only supported 8-bit access to a 16-bit flash device rather than
16-bit access, but this problem was fixed in the next revision. The
platform-specific initialization function can figure out which model
board it is running on and replace the default
<TT
CLASS="LITERAL"
>16as8</TT
> functions with faster <TT
CLASS="LITERAL"
>16</TT
>
ones.
</P
></DIV
><DIV
CLASS="REFSECT2"
><A
NAME="AM29XXXXX-INSTANCE-FUNCTIONS-ERASE-PROGRAM"
></A
><H3
>Erase and Program</H3
><P
>The AM29xxxxx driver provides erase and program functions appropriate
for the various bus configurations. On most targets these can be used
directly. On some targets it may be necessary to do some extra work
before and after the erase and program operations. For example if the
hardware has an MMU then the part of the address map containing the
flash may have been set to read-only, in an attempt to catch spurious
memory accesses. Erasing or programming the flash requires
write-access, so the MMU settings have to be changed temporarily. As
another example some flash device may require a higher voltage to be
applied during an erase or program operation. or a higher voltage may
be desirable to make the operation proceed faster. A typical
platform-specific erase function would look like this:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>static int
alaia_flash_erase(struct cyg_flash_dev* dev, cyg_flashaddr_t addr)
{
int result;
… // Set up the hardware for an erase
result = cyg_am29xxxxx_erase_32(dev, addr);
… // Revert the hardware change
return result;
}
</PRE
></TD
></TR
></TABLE
><P
>There are two configurations which affect the erase and program
functions, and which a platform HAL may wish to change:
<CODE
CLASS="VARNAME"
>CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_TIMEOUT</CODE
>
and
<CODE
CLASS="VARNAME"
>CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_PROGRAM_TIMEOUT</CODE
>.
The erase and program operations both involve polling for completion,
and these timeout impose an upper bound on the polling loop. Normally
these operations should never take anywhere close to the timeout
period, so a timeout indicates a catastrophic failure that should
really be handled by a watchdog reset. A reset is particularly
appropriate because there will be no clean way of aborting the flash
operation. The main reason for the timeouts is to help with debugging
when porting to new hardware. If there is a valid reason why a
particular platform needs different timeouts then the platform HAL's
CDL can require appropriate values for these options.
</P
></DIV
><DIV
CLASS="REFSECT2"
><A
NAME="AM29XXXXX-INSTANCE-FUNCTIONS-LOCKING"
></A
><H3
>Locking</H3
><P
>There is no single way of implementing the block lock and unlock
operations on all AM29xxxxx devices. If these operations are supported at
all then usually they involve manipulating the voltages on certain
pins. This would not be able to be handled by generic driver code since it requires
knowing how these pins can be manipulated via the processor's GPIO
lines. Therefore the AM29xxxxx driver does not usually provide lock and unlock
functions, and instead the generic dummy functions
<CODE
CLASS="FUNCTION"
>cyg_flash_devfn_lock_nop</CODE
> and
<CODE
CLASS="FUNCTION"
>cyg_flash_devfn_unlock_nop</CODE
> should be used. An <A
HREF="am29xxxxx-instance.html#AM29XXXXX-AT49XXXX-LOCKING"
>exception</A
> exists for
the AT49xxxx family of devices which are sufficiently AMD
compatible in other respects. Otherwise, if a
platform does provide a way of implementing the locking then this can
be handled by platform-specific functions.
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>static int
alaia_lock(struct cyg_flash_dev* dev, const cyg_flashaddr_t addr)
{
…
}
static int
alaia_unlock(struct cyg_flash_dev* dev, const cyg_flashaddr_t addr)
{
…
}
</PRE
></TD
></TR
></TABLE
><P
>If real locking functions are implemented then the platform HAL's CDL
script should implement the CDL interface
<CODE
CLASS="VARNAME"
>CYGHWR_IO_FLASH_BLOCK_LOCKING</CODE
>. Otherwise the
generic flash package may believe that none of the flash drivers in the
system provide locking functionality and disable the interface functions.
</P
><DIV
CLASS="REFSECT3"
><A
NAME="AM29XXXXX-AT49XXXX-LOCKING"
></A
><H4
>AT49xxxx locking</H4
><P
>As locking is standardised across the AT49xxxx family of AMD AM29xxxxx
compatible Flash parts, a method supporting this is included within this
driver. <CODE
CLASS="FUNCTION"
>cyg_at49xxxx_softlock_XX</CODE
> provides a means of
locking a Flash sector such that it may be subsequently unlocked.
<CODE
CLASS="FUNCTION"
>cyg_at49xxxx_hardlock_XX</CODE
> locks a sector such that
it cannot be unlocked until after reset or a power cycle.
<CODE
CLASS="FUNCTION"
>cyg_at49xxxx_unlock_XX</CODE
> unlocks a sector that has
previously been softlocked. At power on or Flash device reset, all sectors
default to being softlocked.
</P
></DIV
></DIV
><DIV
CLASS="REFSECT2"
><A
NAME="AM29XXXXX-INSTANCE-FUNCTIONS-OTHER"
></A
><H3
>Other</H3
><P
>The driver provides a set of functions
<CODE
CLASS="FUNCTION"
>cyg_am29xxxxx_read_devid_XX</CODE
>, one per supported
bus configuration. These functions take a single argument, a pointer
to the <CODE
CLASS="STRUCTNAME"
>cyg_flash_dev</CODE
> structure, and return
the chip's device id. For older devices this id is a single byte. For
more recent devices the id is a 3-byte value, 0x7E followed by a
further two bytes that actually identify the device.
<CODE
CLASS="FUNCTION"
>cyg_am29xxxxx_read_devid_XX</CODE
> is usually called
only from inside a platform-specific driver initialization routine,
allowing the platform HAL to adapt to the actual device present on the
board.
</P
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AM29XXXXX-INSTANCE-DEVPRIV"
></A
><H2
>Device-Specific Structure</H2
><P
>The <CODE
CLASS="STRUCTNAME"
>cyg_am29xxxxx_dev</CODE
> structure provides
information specific to AM29xxxxx flash devices, as opposed to the
more generic flash information which goes into the
<CODE
CLASS="STRUCTNAME"
>cyg_flash_dev</CODE
> structure. There are only two
fields: <CODE
CLASS="STRUCTFIELD"
>devid</CODE
> and
<CODE
CLASS="STRUCTFIELD"
>block_info</CODE
>.
</P
><P
><CODE
CLASS="STRUCTFIELD"
>devid</CODE
> is only needed if the driver's
initialization function is set to
<CODE
CLASS="FUNCTION"
>cyg_am29xxxxx_init_check_devid_XX</CODE
>. That function
will extract the actual device info from the flash chip and compare it
with the <CODE
CLASS="STRUCTFIELD"
>devid</CODE
> field. If there is a
mismatch then subsequent operations on the device will fail.
</P
><P
>The <CODE
CLASS="STRUCTFIELD"
>block_info</CODE
> field consists of one or
more pairs of the block size in bytes and the number of blocks of that
size. The order must match the actual hardware device since the flash
code will use the table to determine the start and end locations of
each block. The table can be initialized in one of three ways:
</P
><P
></P
><OL
TYPE="1"
><LI
><P
>If the driver initialization function is set to
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?