You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/03/02 17:05:17 UTC

[incubator-nuttx] branch pr415 updated: boards/z80/ez80/z20x/: Add W25 bootloader

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch pr415
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/pr415 by this push:
     new e814977  boards/z80/ez80/z20x/:  Add W25 bootloader
e814977 is described below

commit e814977c0fffd504fa47579fd000e6fb4143beb5
Author: Gregory Nutt <gn...@nuttx.org>
AuthorDate: Sun Mar 1 11:30:08 2020 -0600

    boards/z80/ez80/z20x/:  Add W25 bootloader
    
    The SD boot loader was not satisfactory because 1) the SD slot is on an optional board and, hence, cannot be part of a fundamental solution.  And 2) it is too big.
    
    The only storage on borard is the Winbond W25 SPI-bsed FLASH.  This commit adds support for a bootload to 1) read code in HEX format from a serial port and write it to the W25 FLASH, or 2) read code in binary form from the W25 FLASH into SRAM and execute the loaded program.
    
    boards/z80/ez80/z20x/configs:  Added w25boot configuration
    boards/z80/ez80/z20x/src:  Add bootloader logic, w25_main.c.  Add logic to manage shared SRAM memory map so that the loaded program does not clobber the bootloader memory.  Add logic to recover the bootloader memory into the heap after the loaded program as started.
    boards/z80/ez80/z20x/scripts:  Rework scripts and configuration to support a bootloader and program build.  The boolloader cannot use all of SRAM; the program must not clobber the SRAM region used by the bootloader.
---
 arch/z80/src/ez80/ez80_spi.c                       |  12 +-
 arch/z80/src/ez80/{ez80f91_spi.h => ez80_spi.h}    |  15 +-
 arch/z80/src/ez80/ez80_startup.asm                 |   1 +
 boards/z80/ez80/makerlisp/src/ez80_spi.c           |  12 +-
 boards/z80/ez80/makerlisp/src/ez80_spimmcsd.c      |  12 +-
 boards/z80/ez80/z20x/Kconfig                       |  71 ++-
 boards/z80/ez80/z20x/configs/w25boot/.gitignore    |   6 +
 boards/z80/ez80/z20x/configs/w25boot/README.txt    |  13 +
 boards/z80/ez80/z20x/configs/w25boot/defconfig     |  40 ++
 .../z80/ez80/z20x/configs/w25boot/sdboot.zdsproj   | 261 +++++++++++
 .../z80/ez80/z20x/configs/w25boot/sdboot.zfpproj   | 315 +++++++++++++
 .../ez80/z20x/configs/w25boot/sdboot_flash.ztgt    |  69 +++
 .../z80/ez80/z20x/configs/w25boot/sdboot_ram.ztgt  |  69 +++
 boards/z80/ez80/z20x/scripts/Make.defs             |  17 +-
 .../{z20x_ram.linkcmd => z20x_loader.linkcmd}      |  25 +-
 .../{z20x_ram.linkcmd => z20x_program.linkcmd}     |  10 +-
 boards/z80/ez80/z20x/src/Makefile                  |   2 +
 boards/z80/ez80/z20x/src/ez80_boot.c               |   7 +
 boards/z80/ez80/z20x/src/ez80_bringup.c            |   6 +-
 boards/z80/ez80/z20x/src/ez80_spi.c                |  12 +-
 boards/z80/ez80/z20x/src/ez80_spimmcsd.c           |  12 +-
 boards/z80/ez80/z20x/src/ez80_w25.c                |  17 +-
 boards/z80/ez80/z20x/src/sd_main.c                 |   9 +-
 boards/z80/ez80/z20x/src/w25_main.c                | 492 +++++++++++++++++++++
 boards/z80/ez80/z20x/src/z20x.h                    |  55 ++-
 25 files changed, 1474 insertions(+), 86 deletions(-)

diff --git a/arch/z80/src/ez80/ez80_spi.c b/arch/z80/src/ez80/ez80_spi.c
index 60d56f2..559da04 100644
--- a/arch/z80/src/ez80/ez80_spi.c
+++ b/arch/z80/src/ez80/ez80_spi.c
@@ -57,19 +57,17 @@
 
 #include "chip.h"
 
-#if defined(CONFIG_ARCH_CHIP_EZ80F91) || defined(CONFIG_ARCH_CHIP_EZ80F92)
-#  include "ez80f91_spi.h"
-#endif
+#include "ez80_spi.h"
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
 #if defined(CONFIG_ARCH_CHIP_EZ80F91) || defined(CONFIG_ARCH_CHIP_EZ80F92)
-#  define GPIOB_SPI_SS      (1 << 2)  /* Pin 2: /SS (not used by driver) */
-#  define GPIOB_SPI_SCK     (1 << 3)  /* Pin 3: SCK */
-#  define GPIOB_SPI_MISO    (1 << 6)  /* Pin 6: MISO */
-#  define GPIOB_SPI_MOSI    (1 << 7)  /* Pin 7: MOSI */
+#  define GPIOB_SPI_SS      (1 << 2)  /* PB2: /SS (not used by driver) */
+#  define GPIOB_SPI_SCK     (1 << 3)  /* PB3: SCK */
+#  define GPIOB_SPI_MISO    (1 << 6)  /* PB6: MISO */
+#  define GPIOB_SPI_MOSI    (1 << 7)  /* PB7: MOSI */
 
 #  define GPIOB_SPI_PINSET  (GPIOB_SPI_SS | GPIOB_SPI_SCK | GPIOB_SPI_MISO | \
                              GPIOB_SPI_MOSI)
diff --git a/arch/z80/src/ez80/ez80f91_spi.h b/arch/z80/src/ez80/ez80_spi.h
similarity index 94%
rename from arch/z80/src/ez80/ez80f91_spi.h
rename to arch/z80/src/ez80/ez80_spi.h
index 97911d1..39809f2 100644
--- a/arch/z80/src/ez80/ez80f91_spi.h
+++ b/arch/z80/src/ez80/ez80_spi.h
@@ -1,7 +1,7 @@
 /************************************************************************************
- * arch/z80/src/ez80/ez80f91_spi.h
+ * arch/z80/src/ez80/ez80_spi.h
  *
- *   Copyright (C) 2009-2010, 2015 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2009-2010, 2015, 2020 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <gn...@nuttx.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,8 +33,8 @@
  *
  ************************************************************************************/
 
-#ifndef __ARCH_Z80_SRC_EZ80_EZ80F91_SPI_H
-#define __ARCH_Z80_SRC_EZ80_EZ80F91_SPI_H
+#ifndef __ARCH_Z80_SRC_EZ80_EZ80_SPI_H
+#define __ARCH_Z80_SRC_EZ80_EZ80_SPI_H
 
 /************************************************************************************
  * Included Files
@@ -51,7 +51,7 @@
 
 /* SPIC Registers  ******************************************************************/
 
-/* Provided in ez80f91.h */
+/* Provided in ez80f9x.h */
 
 /* SPIC Register Bit Definitions  ***************************************************/
 
@@ -63,6 +63,7 @@
 /* SPI Control (CTL) Register Definitions */
 
 #define SPI_CTL_IRQEN    (1 << 7) /* Bit 7: 1=SPI system interrupt is enabled */
+                                  /* Bit 6: Reserved */
 #define SPI_CTL_SPIEN    (1 << 5) /* Bit 5: 1=SPI is enabled */
 #define SPI_CTL_MASTEREN (1 << 4) /* Bit 4: 1=SPI operates as a master */
 #define SPI_CTL_CPOL     (1 << 3) /* Bit 3: 1=Master SCK pin idles in a high (1) state */
@@ -73,7 +74,9 @@
 
 #define SPI_SR_SPIF      (1 << 7) /* Bit 7: 1=SPI data transfer is finished */
 #define SPI_SR_WCOL      (1 << 6) /* Bit 6: 1=SPI write collision is detected*/
+                                  /* Bit 5: Reserved */
 #define SPI_SR_MODF      (1 << 4) /* Bit 4: 1=Mode fault (multimaster conflict) is detected */
+                                  /* Bits 0-3: Reserved */
 
 /* RBR/TSR Register Definitions */
 
@@ -155,4 +158,4 @@ int ez80_spicmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd);
 #endif /* __cplusplus */
 #endif /* __ASSEMBLY__ */
 
-#endif /* __ARCH_Z80_SRC_EZ80_EZ80F91_SPI_H */
+#endif /* __ARCH_Z80_SRC_EZ80_EZ80_SPI_H */
diff --git a/arch/z80/src/ez80/ez80_startup.asm b/arch/z80/src/ez80/ez80_startup.asm
index 93943f2..b1b863b 100644
--- a/arch/z80/src/ez80/ez80_startup.asm
+++ b/arch/z80/src/ez80/ez80_startup.asm
@@ -102,6 +102,7 @@ _ez80_startup:
 
 	; Position the IDLE task stack point at an offset of 1Kb in on-chip SRAM
 	; On-chip SRAM resides at an offset of %00e000 from the RAM base address.
+	; REVISIT:  CONFIG_IDLETHREAD_STACKSIZE is not used!
 
 	ld		sp, __RAM_ADDR_U_INIT_PARAM << 16 + %00e400
 
diff --git a/boards/z80/ez80/makerlisp/src/ez80_spi.c b/boards/z80/ez80/makerlisp/src/ez80_spi.c
index 9448f01..c9b2599 100644
--- a/boards/z80/ez80/makerlisp/src/ez80_spi.c
+++ b/boards/z80/ez80/makerlisp/src/ez80_spi.c
@@ -1,4 +1,4 @@
-/*****************************************************************************
+/****************************************************************************
  * boards/z80/ez80/makerlisp/src/ez80_spi.c
  *
  *   Copyright (C) 2019 Greg Nutt. All rights reserved.
@@ -32,7 +32,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  ****************************************************************************/
 
-/*****************************************************************************
+/****************************************************************************
  * Included Files
  ****************************************************************************/
 
@@ -44,10 +44,10 @@
 
 #include "chip.h"
 #include "z80_internal.h"
-#include "ez80f91_spi.h"
+#include "ez80_spi.h"
 #include "makerlisp.h"
 
-/*****************************************************************************
+/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
@@ -55,7 +55,7 @@
  * Then we don't need to Card Detect callback here.
  */
 
-/*****************************************************************************
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -92,7 +92,7 @@ void ez80_spidev_initialize(void)
 #endif
 }
 
-/*****************************************************************************
+/****************************************************************************
  * The external functions, ez80_spiselect, ez80_spistatus, and
  * ez80_spicmddata must be provided by board-specific logic.  These are
  * implementations of the select, status, and cmddata methods of the SPI
diff --git a/boards/z80/ez80/makerlisp/src/ez80_spimmcsd.c b/boards/z80/ez80/makerlisp/src/ez80_spimmcsd.c
index b455b7f..09450f3 100644
--- a/boards/z80/ez80/makerlisp/src/ez80_spimmcsd.c
+++ b/boards/z80/ez80/makerlisp/src/ez80_spimmcsd.c
@@ -1,4 +1,4 @@
-/*****************************************************************************
+/****************************************************************************
  * boards/z80/ez80/makerlisp/src/ez80_spimmcsd.c
  *
  *   Copyright (C) 2019 Greg Nutt. All rights reserved.
@@ -32,7 +32,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  ****************************************************************************/
 
-/*****************************************************************************
+/****************************************************************************
  * Included Files
  ****************************************************************************/
 
@@ -48,12 +48,12 @@
 #include <nuttx/spi/spi.h>
 
 #include "chip.h"
-#include "ez80f91_spi.h"
+#include "ez80_spi.h"
 #include "makerlisp.h"
 
 #ifdef HAVE_MMCSD
 
-/*****************************************************************************
+/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
@@ -64,11 +64,11 @@
  * 2. Media Change callbacks are not yet implemented in the SPI driver.
  */
 
-/*****************************************************************************
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
-/*****************************************************************************
+/****************************************************************************
  * Name: ez80_mmcsd_initialize
  *
  * Description:
diff --git a/boards/z80/ez80/z20x/Kconfig b/boards/z80/ez80/z20x/Kconfig
index 95eb696..725c3e3 100644
--- a/boards/z80/ez80/z20x/Kconfig
+++ b/boards/z80/ez80/z20x/Kconfig
@@ -5,10 +5,53 @@
 
 if ARCH_BOARD_Z20X
 
+config Z20X_BOOTLOADER
+	bool
+	default n
+	select BOOT_RUNFROMFLASH
+
+choice
+	prompt "Build selection"
+	default Z20X_PROGRAM
+
+config Z20X_SDBOOT
+	bool "SD boot loader"
+	select LIB_HEX2BIN
+	select Z20X_BOOTLOADER
+	depends on EZ80_SPI && MMCSD_SPI
+	---help---
+		Select this option only with the boards/z20x/sdboot
+		configuration.  This will enable the components needed only by the
+		boot loader.
+
+config Z20X_W25BOOT
+	bool "W25 boot loader"
+	select Z20X_W25_CHARDEV
+	select LIB_HEX2BIN
+	select Z20X_BOOTLOADER
+	depends on EZ80_SPI && MTD_W25
+	---help---
+		Select this option only with the boards/z20x/w25boot
+		configuration.  This will enable the components needed only by the
+		boot loader.
+
+config Z20X_PROGRAM
+	bool "Loadable program"
+	select CONFIG_BOOT_RUNFROMEXTSRAM
+	---help---
+		Normal program that resides on SD card or in W25 FLASH and is
+		loaded into RAM by a bootloader.
+
+config Z20X_STANDALONE
+	bool "Standalone FLASH progroam"
+	select BOOT_RUNFROMFLASH
+	---help---
+		Select this option only to build a small program that executes
+		from z20x FLASH memory.
+
 config Z20X_COPYTORAM
 	bool "Copy to RAM"
-	default n
-	depends on BOOT_RUNFROMEXTSRAM
+	select BOOT_RUNFROMEXTSRAM
 	---help---
 		This option is available only when running from external SRAM
 		(CONFIG_BOOT_RUNFROMEXTSRAM).  In that case there are two possible
@@ -17,13 +60,18 @@ config Z20X_COPYTORAM
 		boots out of FLASH, copies itself to SRAM, and runs from SRAM.  This
 		configuration setting selects that latter option.
 
-config Z20X_SDBOOT
-	bool "Build SD boot loader"
-	default n
+endchoice
+
+config Z20X_W25_PROGSIZE
+	int "W25 partition size"
+	default 262144
+	range 131072 524288
+	depends on Z20X_W25BOOT
 	---help---
-		Select this option only with the boards/z20x/sdboot
-		configuration.  This will enable the components needed only by the
-		boot loader.
+		This is the size of the partition at the beginning to the W25
+		serial FLASH that will be used to hold the boot program.  Since
+		this program must run from SRAM, there would be no purpose int
+		making this size any larger than the size of the internal SRAM.
 
 choice
 	prompt "Winbond W25 Usage"
@@ -41,4 +89,11 @@ config Z20X_W25_MTDDEV
 	bool "MTD device"
 
 endchoice
+
+config Z20X_W25_MINOR
+	int "W25 device minor number"
+	default 0
+	range 0 255
+	depends on Z20X_W25_CHARDEV
+
 endif # ARCH_BOARD_Z20X
diff --git a/boards/z80/ez80/z20x/configs/w25boot/.gitignore b/boards/z80/ez80/z20x/configs/w25boot/.gitignore
new file mode 100644
index 0000000..23b9603
--- /dev/null
+++ b/boards/z80/ez80/z20x/configs/w25boot/.gitignore
@@ -0,0 +1,6 @@
+sdboot.hex
+sdboot.map
+sdboot.lod
+sdboot.wsp
+*.asm
+Debug
diff --git a/boards/z80/ez80/z20x/configs/w25boot/README.txt b/boards/z80/ez80/z20x/configs/w25boot/README.txt
new file mode 100644
index 0000000..963af49
--- /dev/null
+++ b/boards/z80/ez80/z20x/configs/w25boot/README.txt
@@ -0,0 +1,13 @@
+README.txt
+^^^^^^^^^^
+
+w25boot.zdsproj is a simple ZDS-II project that will allow you
+  to use the ZDS-II debugger.
+w25boot.zfpproj is a simple project that will allow you to use the Smart Flash
+  Programming.  NOTE:  As of this writing this project does not work, probably
+  due to RAM configuration in the project.  Use ZDS-II instead as is described
+  in the upper README.txt file
+w25boot_flash.ztgt is the target file that accompanies the project files.  This
+  one is identical to boards/scripts/z20x_ram.ztgt.
+w25boot_ram.ztgt is the target file that accompanies the project files.  This
+  one is identical to boards/scripts/z20x_flash.ztgt.
diff --git a/boards/z80/ez80/z20x/configs/w25boot/defconfig b/boards/z80/ez80/z20x/configs/w25boot/defconfig
new file mode 100644
index 0000000..e1a96be
--- /dev/null
+++ b/boards/z80/ez80/z20x/configs/w25boot/defconfig
@@ -0,0 +1,40 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+CONFIG_ARCH="z80"
+CONFIG_ARCH_BOARD="z20x"
+CONFIG_ARCH_BOARD_Z20X=y
+CONFIG_ARCH_CHIP="ez80"
+CONFIG_ARCH_CHIP_EZ80=y
+CONFIG_ARCH_CHIP_EZ80F92=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_Z80=y
+CONFIG_BOARD_LOOPSPERMSEC=1250
+CONFIG_DISABLE_MQUEUE=y
+CONFIG_EZ80_SPI=y
+CONFIG_EZ80_UART1=y
+CONFIG_HOST_WINDOWS=y
+CONFIG_MAX_TASKS=8
+CONFIG_MAX_WDOGPARMS=2
+CONFIG_MTD=y
+CONFIG_MTD_W25=y
+CONFIG_NFILE_DESCRIPTORS=6
+CONFIG_NFILE_STREAMS=6
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PREALLOC_WDOGS=4
+CONFIG_PTHREAD_STACK_DEFAULT=1024
+CONFIG_RAM_SIZE=65536
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_START_MONTH=3
+CONFIG_START_YEAR=2020
+CONFIG_UART1_BITS=0
+CONFIG_UART1_RXBUFSIZE=64
+CONFIG_UART1_SERIAL_CONSOLE=y
+CONFIG_UART1_TXBUFSIZE=64
+CONFIG_USER_ENTRYPOINT="w25_main"
+CONFIG_WDOG_INTRESERVE=1
+CONFIG_Z20X_W25BOOT=y
diff --git a/boards/z80/ez80/z20x/configs/w25boot/sdboot.zdsproj b/boards/z80/ez80/z20x/configs/w25boot/sdboot.zdsproj
new file mode 100644
index 0000000..2ee448c
--- /dev/null
+++ b/boards/z80/ez80/z20x/configs/w25boot/sdboot.zdsproj
@@ -0,0 +1,261 @@
+<project type="Executable" project-type="Standard" configuration="Release" created-by="d:5.3.0:17021001" modified-by="d:5.3.0:19052909" ZDSII="ZDSII - eZ80Acclaim! 5.3.3 (Build 19083001)">
+<cpu>eZ80F92</cpu>
+
+<!-- file information -->
+<files>
+<file filter-key="flash">..\..\..\nuttx.hex</file>
+</files>
+
+<!-- configuration information -->
+<configurations>
+<configuration name="Debug" >
+<tools>
+<tool name="Assembler">
+<options>
+<option name="define" type="string" change-action="assemble">_EZ80ACCLAIM!=1</option>
+<option name="include" type="string" change-action="assemble"></option>
+<option name="list" type="boolean" change-action="none">true</option>
+<option name="listmac" type="boolean" change-action="none">false</option>
+<option name="name" type="boolean" change-action="none">true</option>
+<option name="pagelen" type="integer" change-action="none">0</option>
+<option name="pagewidth" type="integer" change-action="none">80</option>
+<option name="quiet" type="boolean" change-action="none">true</option>
+<option name="sdiopt" type="boolean" change-action="compile">true</option>
+</options>
+</tool>
+<tool name="Compiler">
+<options>
+<option name="padbranch" type="string" change-action="compile">Off</option>
+<option name="define" type="string" change-action="compile">_DEBUG,_EZ80F92,_EZ80ACCLAIM!</option>
+<option name="genprintf" type="boolean" change-action="compile">false</option>
+<option name="keepasm" type="boolean" change-action="none">false</option>
+<option name="keeplst" type="boolean" change-action="none">true</option>
+<option name="list" type="boolean" change-action="none">false</option>
+<option name="listinc" type="boolean" change-action="none">false</option>
+<option name="modsect" type="boolean" change-action="compile">false</option>
+<option name="optspeed" type="boolean" change-action="compile">true</option>
+<option name="promote" type="boolean" change-action="compile">true</option>
+<option name="reduceopt" type="boolean" change-action="compile">false</option>
+<option name="stdinc" type="string" change-action="compile"></option>
+<option name="usrinc" type="string" change-action="compile"></option>
+<option name="watch" type="boolean" change-action="none">false</option>
+<option name="multithread" type="boolean" change-action="compile">false</option>
+</options>
+</tool>
+<tool name="Debugger">
+<options>
+<option name="target" type="string" change-action="rebuild">w25boot_ram</option>
+<option name="debugtool" type="string" change-action="none">USBSmartCable</option>
+<option name="usepageerase" type="boolean" change-action="none">true</option>
+</options>
+</tool>
+<tool name="FlashProgrammer">
+<options>
+<option name="erasebeforeburn" type="boolean" change-action="none">false</option>
+<option name="eraseinfopage" type="boolean" change-action="none">false</option>
+<option name="enableinfopage" type="boolean" change-action="none">false</option>
+<option name="includeserial" type="boolean" change-action="none">false</option>
+<option name="offset" type="integer" change-action="none">0</option>
+<option name="snenable" type="boolean" change-action="none">false</option>
+<option name="sn" type="string" change-action="none">0</option>
+<option name="snsize" type="integer" change-action="none">0</option>
+<option name="snstep" type="integer" change-action="none">0</option>
+<option name="snstepformat" type="integer" change-action="none">0</option>
+<option name="snaddress" type="string" change-action="none">0</option>
+<option name="snformat" type="integer" change-action="none">0</option>
+<option name="snbigendian" type="boolean" change-action="none">true</option>
+<option name="singleval" type="string" change-action="none">0</option>
+<option name="singlevalformat" type="integer" change-action="none">0</option>
+<option name="usepageerase" type="boolean" change-action="none">false</option>
+<option name="useinfopage" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="General">
+<options>
+<option name="warn" type="boolean" change-action="none">true</option>
+<option name="debug" type="boolean" change-action="assemble">true</option>
+<option name="debugcache" type="boolean" change-action="none">true</option>
+<option name="igcase" type="boolean" change-action="assemble">false</option>
+<option name="outputdir" type="string" change-action="compile">Debug\</option>
+</options>
+</tool>
+<tool name="Librarian">
+<options>
+<option name="outfile" type="string" change-action="build">..\..\..\nuttx.lib</option>
+</options>
+</tool>
+<tool name="Linker">
+<options>
+<option name="directives" type="string" change-action="build"></option>
+<option name="createnew" type="boolean" change-action="build">true</option>
+<option name="exeform" type="string" change-action="build">OMF695,INTEL32</option>
+<option name="linkctlfile" type="string" change-action="build"></option>
+<option name="map" type="boolean" change-action="none">true</option>
+<option name="maxhexlen" type="integer" change-action="build">64</option>
+<option name="objlibmods" type="string" change-action="build"></option>
+<option name="of" type="string" change-action="build">..\..\..\nuttx</option>
+<option name="quiet" type="boolean" change-action="none">true</option>
+<option name="relist" type="boolean" change-action="build">false</option>
+<option name="startuptype" type="string" change-action="build">Standard</option>
+<option name="startuplnkcmds" type="boolean" change-action="build">true</option>
+<option name="usecrun" type="boolean" change-action="build">false</option>
+<option name="warnoverlap" type="boolean" change-action="none">true</option>
+<option name="xref" type="boolean" change-action="none">true</option>
+<option name="undefisfatal" type="boolean" change-action="none">true</option>
+<option name="warnisfatal" type="boolean" change-action="none">false</option>
+<option name="sort" type="string" change-action="none">NAME</option>
+<option name="padhex" type="boolean" change-action="build">false</option>
+<option name="fplib" type="string" change-action="build">Real</option>
+<option name="useadddirectives" type="boolean" change-action="build">false</option>
+<option name="linkconfig" type="string" change-action="build">Standard</option>
+<option name="flashinfo" type="string" change-action="build">000000-0000FF</option>
+<option name="ram" type="string" change-action="build">040000-0FFFFF</option>
+<option name="rom" type="string" change-action="build">000000-01FFFF</option>
+<option name="extio" type="string" change-action="build">000000-00FFFF</option>
+<option name="intio" type="string" change-action="build">000000-0000FF</option>
+</options>
+</tool>
+<tool name="Middleware">
+<options>
+<option name="usezsl" type="boolean" change-action="rebuild">false</option>
+<option name="zslports" type="string" change-action="rebuild"></option>
+<option name="zsluarts" type="string" change-action="rebuild"></option>
+<option name="userzk" type="boolean" change-action="rebuild">false</option>
+<option name="rzkconfigpi" type="boolean" change-action="rebuild">true</option>
+<option name="rzkconfigmini" type="boolean" change-action="rebuild">false</option>
+<option name="rzkcomps" type="string" change-action="rebuild"></option>
+</options>
+</tool>
+</tools>
+</configuration>
+<configuration name="Release" >
+<tools>
+<tool name="Assembler">
+<options>
+<option name="define" type="string" change-action="assemble">_EZ80ACCLAIM!=1</option>
+<option name="include" type="string" change-action="assemble"></option>
+<option name="list" type="boolean" change-action="none">false</option>
+<option name="listmac" type="boolean" change-action="none">false</option>
+<option name="name" type="boolean" change-action="none">true</option>
+<option name="pagelen" type="integer" change-action="none">0</option>
+<option name="pagewidth" type="integer" change-action="none">80</option>
+<option name="quiet" type="boolean" change-action="none">true</option>
+<option name="sdiopt" type="boolean" change-action="compile">true</option>
+</options>
+</tool>
+<tool name="Compiler">
+<options>
+<option name="padbranch" type="string" change-action="compile">Off</option>
+<option name="define" type="string" change-action="compile">NDEBUG,_EZ80F92,_EZ80ACCLAIM!</option>
+<option name="genprintf" type="boolean" change-action="compile">false</option>
+<option name="keepasm" type="boolean" change-action="none">false</option>
+<option name="keeplst" type="boolean" change-action="none">false</option>
+<option name="list" type="boolean" change-action="none">false</option>
+<option name="listinc" type="boolean" change-action="none">false</option>
+<option name="modsect" type="boolean" change-action="compile">false</option>
+<option name="optspeed" type="boolean" change-action="compile">true</option>
+<option name="promote" type="boolean" change-action="compile">true</option>
+<option name="reduceopt" type="boolean" change-action="compile">false</option>
+<option name="stdinc" type="string" change-action="compile"></option>
+<option name="usrinc" type="string" change-action="compile"></option>
+<option name="watch" type="boolean" change-action="none">false</option>
+<option name="multithread" type="boolean" change-action="compile">false</option>
+</options>
+</tool>
+<tool name="Debugger">
+<options>
+<option name="target" type="string" change-action="rebuild">w25boot_flash</option>
+<option name="debugtool" type="string" change-action="none">USBSmartCable</option>
+<option name="usepageerase" type="boolean" change-action="none">true</option>
+</options>
+</tool>
+<tool name="FlashProgrammer">
+<options>
+<option name="erasebeforeburn" type="boolean" change-action="none">true</option>
+<option name="eraseinfopage" type="boolean" change-action="none">false</option>
+<option name="enableinfopage" type="boolean" change-action="none">false</option>
+<option name="includeserial" type="boolean" change-action="none">false</option>
+<option name="offset" type="integer" change-action="none">0</option>
+<option name="snenable" type="boolean" change-action="none">false</option>
+<option name="sn" type="string" change-action="none">0</option>
+<option name="snsize" type="integer" change-action="none">0</option>
+<option name="snstep" type="integer" change-action="none">0</option>
+<option name="snstepformat" type="integer" change-action="none">0</option>
+<option name="snaddress" type="string" change-action="none">0</option>
+<option name="snformat" type="integer" change-action="none">0</option>
+<option name="snbigendian" type="boolean" change-action="none">true</option>
+<option name="singleval" type="string" change-action="none">0</option>
+<option name="singlevalformat" type="integer" change-action="none">0</option>
+<option name="usepageerase" type="boolean" change-action="none">false</option>
+<option name="useinfopage" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="General">
+<options>
+<option name="warn" type="boolean" change-action="none">true</option>
+<option name="debug" type="boolean" change-action="assemble">true</option>
+<option name="debugcache" type="boolean" change-action="none">true</option>
+<option name="igcase" type="boolean" change-action="assemble">false</option>
+<option name="outputdir" type="string" change-action="compile">..\..\..\nuttx\</option>
+</options>
+</tool>
+<tool name="Librarian">
+<options>
+<option name="outfile" type="string" change-action="build">..\..\..\nuttx.lib</option>
+</options>
+</tool>
+<tool name="Linker">
+<options>
+<option name="directives" type="string" change-action="build"></option>
+<option name="createnew" type="boolean" change-action="build">true</option>
+<option name="exeform" type="string" change-action="build">OMF695,INTEL32</option>
+<option name="linkctlfile" type="string" change-action="build"></option>
+<option name="map" type="boolean" change-action="none">true</option>
+<option name="maxhexlen" type="integer" change-action="build">64</option>
+<option name="objlibmods" type="string" change-action="build"></option>
+<option name="of" type="string" change-action="build">..\..\..\nuttx</option>
+<option name="quiet" type="boolean" change-action="none">true</option>
+<option name="relist" type="boolean" change-action="build">false</option>
+<option name="startuptype" type="string" change-action="build">Standard</option>
+<option name="startuplnkcmds" type="boolean" change-action="build">true</option>
+<option name="usecrun" type="boolean" change-action="build">true</option>
+<option name="warnoverlap" type="boolean" change-action="none">true</option>
+<option name="xref" type="boolean" change-action="none">true</option>
+<option name="undefisfatal" type="boolean" change-action="none">true</option>
+<option name="warnisfatal" type="boolean" change-action="none">false</option>
+<option name="sort" type="string" change-action="none">NAME</option>
+<option name="padhex" type="boolean" change-action="build">false</option>
+<option name="fplib" type="string" change-action="build">Real</option>
+<option name="useadddirectives" type="boolean" change-action="build">false</option>
+<option name="linkconfig" type="string" change-action="build">Standard</option>
+<option name="flashinfo" type="string" change-action="build">000000-0000FF</option>
+<option name="ram" type="string" change-action="build">040000-0BFFFF</option>
+<option name="rom" type="string" change-action="build">000000-01FFFF</option>
+<option name="extio" type="string" change-action="build">000000-00FFFF</option>
+<option name="intio" type="string" change-action="build">000000-0000FF</option>
+</options>
+</tool>
+<tool name="Middleware">
+<options>
+<option name="usezsl" type="boolean" change-action="rebuild">false</option>
+<option name="zslports" type="string" change-action="rebuild"></option>
+<option name="zsluarts" type="string" change-action="rebuild"></option>
+<option name="userzk" type="boolean" change-action="rebuild">false</option>
+<option name="rzkconfigpi" type="boolean" change-action="rebuild">true</option>
+<option name="rzkconfigmini" type="boolean" change-action="rebuild">false</option>
+<option name="rzkcomps" type="string" change-action="rebuild"></option>
+</options>
+</tool>
+</tools>
+</configuration>
+</configurations>
+
+<!-- watch information -->
+<watch-elements>
+</watch-elements>
+
+<!-- breakpoint information -->
+<breakpoints>
+</breakpoints>
+
+</project>
diff --git a/boards/z80/ez80/z20x/configs/w25boot/sdboot.zfpproj b/boards/z80/ez80/z20x/configs/w25boot/sdboot.zfpproj
new file mode 100644
index 0000000..602c81c
--- /dev/null
+++ b/boards/z80/ez80/z20x/configs/w25boot/sdboot.zfpproj
@@ -0,0 +1,315 @@
+<project type="Standard" project-type="Standard" configuration="Debug" created-by="{{build_number}}" modified-by="{{build_number}}">
+<cpu>eZ80F92</cpu>
+
+<!-- file information -->
+<files>
+<file filter-key="flash">..\..\..\nuttx.hex</file>
+</files>
+
+<!-- configuration information -->
+<configurations>
+<configuration name="Debug" >
+<tools>
+<tool name="Assembler">
+<options>
+<option name="debug" type="boolean" change-action="assemble">true</option>
+<option name="define" type="string" change-action="assemble">_EZ80ACCLAIM!=1</option>
+<option name="genobj" type="boolean" change-action="assemble">true</option>
+<option name="igcase" type="boolean" change-action="assemble">false</option>
+<option name="include" type="string" change-action="assemble"></option>
+<option name="list" type="boolean" change-action="none">true</option>
+<option name="listmac" type="boolean" change-action="none">false</option>
+<option name="name" type="boolean" change-action="none">true</option>
+<option name="pagelen" type="integer" change-action="none">56</option>
+<option name="pagewidth" type="integer" change-action="none">80</option>
+<option name="quiet" type="boolean" change-action="none">true</option>
+<option name="sdiopt" type="boolean" change-action="assemble">true</option>
+<option name="warn" type="boolean" change-action="none">true</option>
+<option name="zmasm" type="boolean" change-action="assemble">false</option>
+</options>
+</tool>
+<tool name="Compiler">
+<options>
+<option name="alias" type="boolean" change-action="compile">true</option>
+<option name="asm" type="boolean" change-action="none">true</option>
+<option name="bitfieldsize" type="integer" change-action="rebuild">24</option>
+<option name="charsize" type="integer" change-action="rebuild">8</option>
+<option name="const" type="string" change-action="compile">RAM</option>
+<option name="debug" type="boolean" change-action="compile">true</option>
+<option name="define" type="string" change-action="compile">_EZ80F92,_EZ80ACCLAIM!</option>
+<option name="doublesize" type="integer" change-action="rebuild">32</option>
+<option name="expmac" type="boolean" change-action="none">false</option>
+<option name="floatsize" type="integer" change-action="rebuild">32</option>
+<option name="fplib" type="boolean" change-action="compile">false</option>
+<option name="genprintf" type="boolean" change-action="compile">true</option>
+<option name="globalcopy" type="boolean" change-action="compile">false</option>
+<option name="globalcse" type="boolean" change-action="compile">false</option>
+<option name="globalfold" type="boolean" change-action="compile">false</option>
+<option name="intrinsic" type="boolean" change-action="compile">true</option>
+<option name="intsize" type="integer" change-action="rebuild">24</option>
+<option name="intsrc" type="boolean" change-action="none">true</option>
+<option name="jmpopt" type="boolean" change-action="compile">false</option>
+<option name="keepasm" type="boolean" change-action="none">false</option>
+<option name="keeplst" type="boolean" change-action="none">false</option>
+<option name="list" type="boolean" change-action="none">false</option>
+<option name="listinc" type="boolean" change-action="none">false</option>
+<option name="localcopy" type="boolean" change-action="compile">true</option>
+<option name="localcse" type="boolean" change-action="compile">true</option>
+<option name="localfold" type="boolean" change-action="compile">true</option>
+<option name="longsize" type="integer" change-action="rebuild">32</option>
+<option name="loopopt" type="boolean" change-action="compile">false</option>
+<option name="maxerrs" type="integer" change-action="none">50</option>
+<option name="modsect" type="boolean" change-action="compile">false</option>
+<option name="optspeed" type="boolean" change-action="compile">false</option>
+<option name="peephole" type="boolean" change-action="compile">true</option>
+<option name="promote" type="boolean" change-action="compile">true</option>
+<option name="quiet" type="boolean" change-action="none">true</option>
+<option name="sdiopt" type="boolean" change-action="compile">false</option>
+<option name="shortsize" type="integer" change-action="rebuild">16</option>
+<option name="stdinc" type="string" change-action="compile"></option>
+<option name="strict" type="boolean" change-action="compile">true</option>
+<option name="usrinc" type="string" change-action="compile"></option>
+<option name="watch" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="Debugger">
+<options>
+<option name="target" type="string" change-action="rebuild">w25boot_flash</option>
+<option name="debugtool" type="string" change-action="none">USBSmartCable</option>
+<option name="debugtoolnames" type="string" change-action="none">ZPAKII</option>
+<option name="SmartEthernetNumbers" type="string" change-action="none">ZPAKII</option>
+<option name="USBSerialNumbers" type="string" change-action="none"></option>
+</options>
+</tool>
+<tool name="FlashProgrammer">
+<options>
+<option name="erasebeforeburn" type="boolean" change-action="none">true</option>
+<option name="pageerasebeforeburn" type="boolean" change-action="none">false</option>
+<option name="eraseinfopage" type="boolean" change-action="none">false</option>
+<option name="enableinfopage" type="boolean" change-action="none">false</option>
+<option name="usenvds" type="boolean" change-action="none">false</option>
+<option name="includeserial" type="boolean" change-action="none">false</option>
+<option name="offset" type="integer" change-action="none">0</option>
+<option name="errorhandling" type="integer" change-action="none">0</option>
+<option name="AutoClose" type="boolean" change-action="none">true</option>
+<option name="DisableWarning" type="boolean" change-action="none">false</option>
+<option name="DisableWarningOnFRP" type="boolean" change-action="none">false</option>
+<option name="snenable" type="boolean" change-action="none">true</option>
+<option name="sn" type="string" change-action="none">000000000000000000000000</option>
+<option name="snsize" type="integer" change-action="none">1</option>
+<option name="snstep" type="integer" change-action="none">000000000000000000000001</option>
+<option name="snstepformat" type="integer" change-action="none">0</option>
+<option name="snaddress" type="string" change-action="none">0</option>
+<option name="snformat" type="integer" change-action="none">0</option>
+<option name="snbigendian" type="boolean" change-action="none">true</option>
+<option name="singleval" type="string" change-action="none">000000000000000000000000</option>
+<option name="singlevalformat" type="integer" change-action="none">0</option>
+<option name="autoselect" type="boolean" change-action="none">true</option>
+<option name="includeoptionbits" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="General">
+<options>
+<option name="outputdir" type="string" change-action="compile">.</option>
+<option name="tempath" type="string" change-action="none"></option>
+</options>
+</tool>
+<tool name="Librarian">
+<options>
+<option name="outfile" type="string" change-action="build"></option>
+<option name="warn" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="Linker">
+<options>
+<option name="directives" type="string" change-action="build"></option>
+<option name="createnew" type="integer" change-action="build">0</option>
+<option name="customlnkflag" type="integer" change-action="build">0</option>
+<option name="debug" type="boolean" change-action="build">true</option>
+<option name="exeform" type="string" change-action="build">OMF695,INTEL32</option>
+<option name="extio" type="string" change-action="build">000000-00FFFF</option>
+<option name="flashinfo" type="string" change-action="build">000000-0001FF</option>
+<option name="igcase" type="boolean" change-action="build">false</option>
+<option name="intio" type="string" change-action="build">000000-0000FF</option>
+<option name="linkctlfile" type="string" change-action="build"></option>
+<option name="map" type="boolean" change-action="none">true</option>
+<option name="maxhexlen" type="integer" change-action="build">64</option>
+<option name="linkconfig" type="integer" change-action="build">1</option>
+<option name="objlibmods" type="string" change-action="build"></option>
+<option name="of" type="string" change-action="build">.\w25boot</option>
+<option name="quiet" type="boolean" change-action="none">false</option>
+<option name="ram" type="string" change-action="build">B7E000-B7FFFF</option>
+<option name="relist" type="boolean" change-action="build">false</option>
+<option name="rom" type="string" change-action="build">000000-01FFFF</option>
+<option name="startup" type="string" change-action="build"></option>
+<option name="startuptype" type="integer" change-action="build">1</option>
+<option name="usebootdirectives" type="boolean" change-action="build">false</option>
+<option name="usecrun" type="boolean" change-action="build">true</option>
+<option name="warn" type="boolean" change-action="none">true</option>
+<option name="warnoverlap" type="boolean" change-action="none">false</option>
+<option name="xref" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="Middleware">
+<options>
+<option name="usezsl" type="boolean" change-action="rebuild">false</option>
+<option name="zslports" type="string" change-action="rebuild"></option>
+<option name="zsluarts" type="string" change-action="rebuild"></option>
+</options>
+</tool>
+</tools>
+</configuration>
+<configuration name="Release" >
+<tools>
+<tool name="Assembler">
+<options>
+<option name="debug" type="boolean" change-action="assemble">false</option>
+<option name="define" type="string" change-action="assemble">_EZ80ACCLAIM!=1</option>
+<option name="genobj" type="boolean" change-action="assemble">true</option>
+<option name="igcase" type="boolean" change-action="assemble">false</option>
+<option name="include" type="string" change-action="assemble"></option>
+<option name="list" type="boolean" change-action="none">true</option>
+<option name="listmac" type="boolean" change-action="none">false</option>
+<option name="name" type="boolean" change-action="none">true</option>
+<option name="pagelen" type="integer" change-action="none">56</option>
+<option name="pagewidth" type="integer" change-action="none">80</option>
+<option name="quiet" type="boolean" change-action="none">true</option>
+<option name="sdiopt" type="boolean" change-action="assemble">true</option>
+<option name="warn" type="boolean" change-action="none">true</option>
+<option name="zmasm" type="boolean" change-action="assemble">false</option>
+</options>
+</tool>
+<tool name="Compiler">
+<options>
+<option name="alias" type="boolean" change-action="compile">true</option>
+<option name="asm" type="boolean" change-action="none">true</option>
+<option name="bitfieldsize" type="integer" change-action="rebuild">24</option>
+<option name="charsize" type="integer" change-action="rebuild">8</option>
+<option name="const" type="string" change-action="compile">RAM</option>
+<option name="debug" type="boolean" change-action="compile">false</option>
+<option name="define" type="string" change-action="compile">_EZ80F92,_EZ80ACCLAIM!</option>
+<option name="doublesize" type="integer" change-action="rebuild">32</option>
+<option name="expmac" type="boolean" change-action="none">false</option>
+<option name="floatsize" type="integer" change-action="rebuild">32</option>
+<option name="fplib" type="boolean" change-action="compile">false</option>
+<option name="genprintf" type="boolean" change-action="compile">true</option>
+<option name="globalcopy" type="boolean" change-action="compile">true</option>
+<option name="globalcse" type="boolean" change-action="compile">true</option>
+<option name="globalfold" type="boolean" change-action="compile">true</option>
+<option name="intrinsic" type="boolean" change-action="compile">true</option>
+<option name="intsize" type="integer" change-action="rebuild">24</option>
+<option name="intsrc" type="boolean" change-action="none">true</option>
+<option name="jmpopt" type="boolean" change-action="compile">true</option>
+<option name="keepasm" type="boolean" change-action="none">false</option>
+<option name="keeplst" type="boolean" change-action="none">false</option>
+<option name="list" type="boolean" change-action="none">false</option>
+<option name="listinc" type="boolean" change-action="none">false</option>
+<option name="localcopy" type="boolean" change-action="compile">true</option>
+<option name="localcse" type="boolean" change-action="compile">true</option>
+<option name="localfold" type="boolean" change-action="compile">true</option>
+<option name="longsize" type="integer" change-action="rebuild">32</option>
+<option name="loopopt" type="boolean" change-action="compile">true</option>
+<option name="maxerrs" type="integer" change-action="none">50</option>
+<option name="modsect" type="boolean" change-action="compile">false</option>
+<option name="optspeed" type="boolean" change-action="compile">false</option>
+<option name="peephole" type="boolean" change-action="compile">true</option>
+<option name="promote" type="boolean" change-action="compile">true</option>
+<option name="quiet" type="boolean" change-action="none">true</option>
+<option name="sdiopt" type="boolean" change-action="compile">true</option>
+<option name="shortsize" type="integer" change-action="rebuild">16</option>
+<option name="stdinc" type="string" change-action="compile"></option>
+<option name="strict" type="boolean" change-action="compile">true</option>
+<option name="usrinc" type="string" change-action="compile"></option>
+<option name="watch" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="Debugger">
+<options>
+<option name="target" type="string" change-action="rebuild">w25boot_flash</option>
+<option name="debugtool" type="string" change-action="none">USBSmartCable</option>
+<option name="debugtoolnames" type="string" change-action="none">ZPAKII</option>
+<option name="SmartEthernetNumbers" type="string" change-action="none">ZPAKII</option>
+<option name="USBSerialNumbers" type="string" change-action="none"></option>
+</options>
+</tool>
+<tool name="FlashProgrammer">
+<options>
+<option name="erasebeforeburn" type="boolean" change-action="none">false</option>
+<option name="pageerasebeforeburn" type="boolean" change-action="none">false</option>
+<option name="eraseinfopage" type="boolean" change-action="none">false</option>
+<option name="enableinfopage" type="boolean" change-action="none">false</option>
+<option name="usenvds" type="boolean" change-action="none">false</option>
+<option name="includeserial" type="boolean" change-action="none">false</option>
+<option name="offset" type="integer" change-action="none">0</option>
+<option name="errorhandling" type="integer" change-action="none">0</option>
+<option name="AutoClose" type="boolean" change-action="none">true</option>
+<option name="DisableWarning" type="boolean" change-action="none">false</option>
+<option name="DisableWarningOnFRP" type="boolean" change-action="none">false</option>
+<option name="snenable" type="boolean" change-action="none">false</option>
+<option name="sn" type="string" change-action="none">0</option>
+<option name="snsize" type="integer" change-action="none">0</option>
+<option name="snstep" type="integer" change-action="none">1</option>
+<option name="snstepformat" type="integer" change-action="none">0</option>
+<option name="snaddress" type="string" change-action="none">0</option>
+<option name="snformat" type="integer" change-action="none">0</option>
+<option name="snbigendian" type="boolean" change-action="none">true</option>
+<option name="singleval" type="string" change-action="none">0</option>
+<option name="singlevalformat" type="integer" change-action="none">0</option>
+<option name="autoselect" type="boolean" change-action="none">true</option>
+<option name="includeoptionbits" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="General">
+<options>
+<option name="outputdir" type="string" change-action="compile">.</option>
+<option name="tempath" type="string" change-action="none"></option>
+</options>
+</tool>
+<tool name="Librarian">
+<options>
+<option name="outfile" type="string" change-action="build"></option>
+<option name="warn" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="Linker">
+<options>
+<option name="directives" type="string" change-action="build"></option>
+<option name="createnew" type="integer" change-action="build">0</option>
+<option name="customlnkflag" type="integer" change-action="build">0</option>
+<option name="debug" type="boolean" change-action="build">false</option>
+<option name="exeform" type="string" change-action="build">OMF695,INTEL32</option>
+<option name="extio" type="string" change-action="build">000000-00FFFF</option>
+<option name="flashinfo" type="string" change-action="build">000000-0001FF</option>
+<option name="igcase" type="boolean" change-action="build">false</option>
+<option name="intio" type="string" change-action="build">000000-0000FF</option>
+<option name="linkctlfile" type="string" change-action="build"></option>
+<option name="map" type="boolean" change-action="none">true</option>
+<option name="maxhexlen" type="integer" change-action="build">64</option>
+<option name="linkconfig" type="integer" change-action="build">1</option>
+<option name="objlibmods" type="string" change-action="build"></option>
+<option name="of" type="string" change-action="build">.\w25boot</option>
+<option name="quiet" type="boolean" change-action="none">false</option>
+<option name="ram" type="string" change-action="build">B7E000-B7FFFF</option>
+<option name="relist" type="boolean" change-action="build">false</option>
+<option name="rom" type="string" change-action="build">000000-01FFFF</option>
+<option name="startup" type="string" change-action="build"></option>
+<option name="startuptype" type="integer" change-action="build">1</option>
+<option name="usebootdirectives" type="boolean" change-action="build">false</option>
+<option name="usecrun" type="boolean" change-action="build">true</option>
+<option name="warn" type="boolean" change-action="none">true</option>
+<option name="warnoverlap" type="boolean" change-action="none">false</option>
+<option name="xref" type="boolean" change-action="none">false</option>
+</options>
+</tool>
+<tool name="Middleware">
+<options>
+<option name="usezsl" type="boolean" change-action="rebuild">false</option>
+<option name="zslports" type="string" change-action="rebuild"></option>
+<option name="zsluarts" type="string" change-action="rebuild"></option>
+</options>
+</tool>
+</tools>
+</configuration>
+</configurations>
+
+</project>
diff --git a/boards/z80/ez80/z20x/configs/w25boot/sdboot_flash.ztgt b/boards/z80/ez80/z20x/configs/w25boot/sdboot_flash.ztgt
new file mode 100644
index 0000000..b691cd5
--- /dev/null
+++ b/boards/z80/ez80/z20x/configs/w25boot/sdboot_flash.ztgt
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Target name="eZ80F920300KITG_Flash" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Schemas/target.tsd" xsi:type="TargetEZ80">
+   <Clock>
+      <PLL>
+         <changeFrequencyOnReset>true</changeFrequencyOnReset>
+         <chargePumpFreq>1f4</chargePumpFreq>
+         <clockLockCriteria>8</clockLockCriteria>
+         <oscFrequency>20000000</oscFrequency>
+      </PLL>
+      <clockType>PLL</clockType>
+      <frequency>20000000</frequency>
+   </Clock>
+   <ControlReg>
+      <pc>0</pc>
+      <splStackPtr>140000</splStackPtr>
+      <spsStackPtr>FFFF</spsStackPtr>
+      <useAdlMode>true</useAdlMode>
+   </ControlReg>
+   <ExtFlash>
+      <device />
+      <externalAddress>200000</externalAddress>
+      <externalAutoSelect>false</externalAutoSelect>
+      <externalRamLower>040000</externalRamLower>
+      <externalRamUpper>0BFFFF</externalRamUpper>
+      <manufacturer />
+      <units>1</units>
+      <usingExternal>false</usingExternal>
+      <usingInternal>true</usingInternal>
+   </ExtFlash>
+   <Memory>
+      <ChipSelects>
+         <CS0>
+            <busMode>0</busMode>
+            <controlRegister>8</controlRegister>
+            <lower>4</lower>
+            <upper>B</upper>
+         </CS0>
+         <CS1>
+            <busMode>0</busMode>
+            <controlRegister>0</controlRegister>
+            <lower>0</lower>
+            <upper>0</upper>
+         </CS1>
+         <CS2>
+            <busMode>0</busMode>
+            <controlRegister>0</controlRegister>
+            <lower>0</lower>
+            <upper>0</upper>
+         </CS2>
+         <CS3>
+            <busMode>0</busMode>
+            <controlRegister>0</controlRegister>
+            <lower>0</lower>
+            <upper>0</upper>
+         </CS3>
+      </ChipSelects>
+      <Internal>
+         <mapFlashToPage>0</mapFlashToPage>
+         <mapRamToPage>AF</mapRamToPage>
+         <useFlashRam>true</useFlashRam>
+         <useInternalDataRam>true</useInternalDataRam>
+         <useMaccRam>false</useMaccRam>
+      </Internal>
+      <waitStates>4</waitStates>
+   </Memory>
+   <cpu>EZ80F92</cpu>
+   <schemaVersion>1.0.1</schemaVersion>
+   <version>1.00</version>
+</Target>
diff --git a/boards/z80/ez80/z20x/configs/w25boot/sdboot_ram.ztgt b/boards/z80/ez80/z20x/configs/w25boot/sdboot_ram.ztgt
new file mode 100644
index 0000000..8f78f6b
--- /dev/null
+++ b/boards/z80/ez80/z20x/configs/w25boot/sdboot_ram.ztgt
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Target name="eZ80F920300KITG_RAM" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Schemas/target.tsd" xsi:type="TargetEZ80">
+   <Clock>
+      <PLL>
+         <changeFrequencyOnReset>true</changeFrequencyOnReset>
+         <chargePumpFreq>1f4</chargePumpFreq>
+         <clockLockCriteria>8</clockLockCriteria>
+         <oscFrequency>20000000</oscFrequency>
+      </PLL>
+      <clockType>PLL</clockType>
+      <frequency>20000000</frequency>
+   </Clock>
+   <ControlReg>
+      <pc>0</pc>
+      <splStackPtr>100000</splStackPtr>
+      <spsStackPtr>ffff</spsStackPtr>
+      <useAdlMode>true</useAdlMode>
+   </ControlReg>
+   <ExtFlash>
+      <device />
+      <externalAddress>200000</externalAddress>
+      <externalAutoSelect>false</externalAutoSelect>
+      <externalRamLower>000000</externalRamLower>
+      <externalRamUpper>FFFFF</externalRamUpper>
+      <manufacturer />
+      <units>1</units>
+      <usingExternal>false</usingExternal>
+      <usingInternal>true</usingInternal>
+   </ExtFlash>
+   <Memory>
+      <ChipSelects>
+         <CS0>
+            <busMode>0</busMode>
+            <controlRegister>8</controlRegister>
+            <lower>0</lower>
+            <upper>7</upper>
+         </CS0>
+         <CS1>
+            <busMode>0</busMode>
+            <controlRegister>0</controlRegister>
+            <lower>0</lower>
+            <upper>0</upper>
+         </CS1>
+         <CS2>
+            <busMode>0</busMode>
+            <controlRegister>0</controlRegister>
+            <lower>0</lower>
+            <upper>0</upper>
+         </CS2>
+         <CS3>
+            <busMode>0</busMode>
+            <controlRegister>0</controlRegister>
+            <lower>0</lower>
+            <upper>0</upper>
+         </CS3>
+      </ChipSelects>
+      <Internal>
+         <mapFlashToPage>0</mapFlashToPage>
+         <mapRamToPage>AF</mapRamToPage>
+         <useFlashRam>false</useFlashRam>
+         <useInternalDataRam>true</useInternalDataRam>
+         <useMaccRam>false</useMaccRam>
+      </Internal>
+      <waitStates>4</waitStates>
+   </Memory>
+   <cpu>EZ80F92</cpu>
+   <schemaVersion>1.0.1</schemaVersion>
+   <version>1.00</version>
+</Target>
diff --git a/boards/z80/ez80/z20x/scripts/Make.defs b/boards/z80/ez80/z20x/scripts/Make.defs
index 71d9b08..eb72efe 100644
--- a/boards/z80/ez80/z20x/scripts/Make.defs
+++ b/boards/z80/ez80/z20x/scripts/Make.defs
@@ -65,13 +65,22 @@ CPPFLAGS = $(CPPDEFINES) $(CPPINCLUDES)
 ARFLAGS = -quiet -warn
 
 # Linker definitions
-
-ifeq ($(CONFIG_BOOT_RUNFROMFLASH),y)
+#
+# Possible configurations
+#
+# 1. FLASH-resident bootloader (CONFIG_Z20X_BOOTLOADER)
+# 2. RAM-resident applications loaded by bootloader (CONFIG_Z20X_PROGRAM)
+# 3. FLASH-resident, standalone program (CONFIG_Z20X_STANDALONE)
+# 4. FLASH-resident, standalone copy-to-RAM program (CONFIG_Z20X_COPYTORAM)
+
+ifeq ($(CONFIG_Z20X_BOOTLOADER),y)
+  LDSCRIPT = z20x_loader.linkcmd
+else ifeq ($(CONFIG_Z20X_PROGRAM),y)
+  LDSCRIPT = z20x_program.linkcmd
+else ifeq ($(CONFIG_Z20X_STANDALONE),y)
   LDSCRIPT = z20x_flash.linkcmd
 else ifeq ($(CONFIG_Z20X_COPYTORAM),y)
   LDSCRIPT = z20x_copytoram.linkcmd
-else # ifeq ($(CONFIG_BOOT_RUNFROMEXTSRAM),y)
-  LDSCRIPT = z20x_ram.linkcmd
 endif
 
 LINKCMDTEMPLATE = $(TOPDIR)$(DELIM)boards$(DELIM)$(CONFIG_ARCH)$(DELIM)$(CONFIG_ARCH_CHIP)$(DELIM)$(CONFIG_ARCH_BOARD)$(DELIM)scripts$(DELIM)$(LDSCRIPT)
diff --git a/boards/z80/ez80/z20x/scripts/z20x_ram.linkcmd b/boards/z80/ez80/z20x/scripts/z20x_loader.linkcmd
similarity index 86%
copy from boards/z80/ez80/z20x/scripts/z20x_ram.linkcmd
copy to boards/z80/ez80/z20x/scripts/z20x_loader.linkcmd
index 966a456..38d869d 100644
--- a/boards/z80/ez80/z20x/scripts/z20x_ram.linkcmd
+++ b/boards/z80/ez80/z20x/scripts/z20x_loader.linkcmd
@@ -1,6 +1,6 @@
 /*****************************************************************************/
-/* boards/z80/ez80/z20x/scripts/z20x_ram.linkcmd                             */
-/* For configurations running entirely out of RAM with nothing in FLASH      */
+/* boards/z80/ez80/z20x/scripts/z20x_loader.linkcmd                          */
+/* For bootloader configurations running entirely out of FLASH               */
 /*                                                                           */
 /* Licensed to the Apache Software Foundation (ASF) under one or more        */
 /* contributor license agreements.  See the NOTICE file distributed with     */
@@ -23,18 +23,15 @@
 -map -maxhexlen=64 -quiet -warnoverlap -xref -unresolved=fatal
 -sort NAME=ascending -warn -debug -NOigcase
 
-RANGE ROM $000000 : $01FFFF
-RANGE RAM $040000 : $0BFFFF
-RANGE EXTIO $000000 : $00FFFF
-RANGE INTIO $000000 : $0000FF
+RANGE ROM $000000 : $01ffff
+RANGE RAM $040000 : $04ffff
+RANGE EXTIO $000000 : $00ffff
+RANGE INTIO $000000 : $0000ff
 
-CHANGE .RESET is RAM
-CHANGE .STARTUP is RAM
-CHANGE TEXT is CODE
-CHANGE CODE is RAM
-CHANGE STRSECT is CODE
+CHANGE STRSECT is ROM
 
 ORDER .RESET,.IVECTS,.STARTUP,CODE,DATA
+COPY DATA ROM
 
 DEFINE __low_romdata = copy base of DATA
 DEFINE __low_data = base of DATA
@@ -50,6 +47,12 @@ DEFINE __len_code = length of CODE
 DEFINE __copy_code_to_ram = 0
 DEFINE __crtl = 1
 
+DEFINE __vecstart = $040000
+DEFINE __loaderstart = $040400
+DEFINE __loaderend = $04ffff
+DEFINE __progstart = $050000
+DEFINE __progend = $0bffff
+
 DEFINE __CS0_LBR_INIT_PARAM = $04
 DEFINE __CS0_UBR_INIT_PARAM = $0b
 DEFINE __CS0_CTL_INIT_PARAM = $08
diff --git a/boards/z80/ez80/z20x/scripts/z20x_ram.linkcmd b/boards/z80/ez80/z20x/scripts/z20x_program.linkcmd
similarity index 93%
rename from boards/z80/ez80/z20x/scripts/z20x_ram.linkcmd
rename to boards/z80/ez80/z20x/scripts/z20x_program.linkcmd
index 966a456..d0949d3 100644
--- a/boards/z80/ez80/z20x/scripts/z20x_ram.linkcmd
+++ b/boards/z80/ez80/z20x/scripts/z20x_program.linkcmd
@@ -1,5 +1,5 @@
 /*****************************************************************************/
-/* boards/z80/ez80/z20x/scripts/z20x_ram.linkcmd                             */
+/* boards/z80/ez80/z20x/scripts/z20x_program.linkcmd                         */
 /* For configurations running entirely out of RAM with nothing in FLASH      */
 /*                                                                           */
 /* Licensed to the Apache Software Foundation (ASF) under one or more        */
@@ -24,7 +24,7 @@
 -sort NAME=ascending -warn -debug -NOigcase
 
 RANGE ROM $000000 : $01FFFF
-RANGE RAM $040000 : $0BFFFF
+RANGE RAM $050000 : $0BFFFF
 RANGE EXTIO $000000 : $00FFFF
 RANGE INTIO $000000 : $0000FF
 
@@ -50,6 +50,12 @@ DEFINE __len_code = length of CODE
 DEFINE __copy_code_to_ram = 0
 DEFINE __crtl = 1
 
+DEFINE __vecstart = $040000
+DEFINE __loaderstart = $040400
+DEFINE __loaderend = $04ffff
+DEFINE __progstart = $050000
+DEFINE __progend = $0bffff
+
 DEFINE __CS0_LBR_INIT_PARAM = $04
 DEFINE __CS0_UBR_INIT_PARAM = $0b
 DEFINE __CS0_CTL_INIT_PARAM = $08
diff --git a/boards/z80/ez80/z20x/src/Makefile b/boards/z80/ez80/z20x/src/Makefile
index 83f54ec..1a6ab01 100644
--- a/boards/z80/ez80/z20x/src/Makefile
+++ b/boards/z80/ez80/z20x/src/Makefile
@@ -36,6 +36,8 @@ endif
 
 ifeq ($(CONFIG_Z20X_SDBOOT),y)
 CSRCS += sd_main.c
+else ifeq ($(CONFIG_Z20X_W25BOOT),y)
+CSRCS += w25_main.c
 endif
 
 ifeq ($(CONFIG_MTD_W25),y)
diff --git a/boards/z80/ez80/z20x/src/ez80_boot.c b/boards/z80/ez80/z20x/src/ez80_boot.c
index 0d3b13c..3f060e8 100644
--- a/boards/z80/ez80/z20x/src/ez80_boot.c
+++ b/boards/z80/ez80/z20x/src/ez80_boot.c
@@ -27,6 +27,7 @@
 #include <stdbool.h>
 
 #include <nuttx/arch.h>
+#include <nuttx/mm/mm.h>
 #include <arch/chip/io.h>
 
 #include "chip.h"
@@ -49,6 +50,12 @@
 
 void ez80_board_initialize(void)
 {
+#ifdef CONFIG_Z20X_PROGRAM
+  /* Recover memory used by the bootloader */
+
+  kmm_addregion((FAR void *)PROGSTART, PROGSIZE);
+#endif
+
 #ifdef CONFIG_EZ80_SPI
   /* Initialize SPI chip selects */
 
diff --git a/boards/z80/ez80/z20x/src/ez80_bringup.c b/boards/z80/ez80/z20x/src/ez80_bringup.c
index f9f1db6..efbb37d 100644
--- a/boards/z80/ez80/z20x/src/ez80_bringup.c
+++ b/boards/z80/ez80/z20x/src/ez80_bringup.c
@@ -59,13 +59,14 @@ int ez80_bringup(void)
   if (ret < 0)
     {
       ferr("ERROR: Failed to mount procfs at /proc: %d\n", ret);
+      return ret;
     }
 #endif
 
 #ifdef HAVE_SPIFLASH
   /* Initialize and register the W25 FLASH file system. */
 
-  ret = ez80_w25_initialize(0);
+  ret = ez80_w25_initialize(CONFIG_Z20X_W25_MINOR);
   if (ret < 0)
     {
       ferr("ERROR: Failed to initialize W25 minor %d: %d\n", 0, ret);
@@ -80,9 +81,10 @@ int ez80_bringup(void)
   if (ret < 0)
     {
       mcerr("ERROR: Failed to initialize SD card: %d\n", ret);
+      return ret;
     }
 #endif
 
   UNUSED(ret);
-  return ret;
+  return OK;
 }
diff --git a/boards/z80/ez80/z20x/src/ez80_spi.c b/boards/z80/ez80/z20x/src/ez80_spi.c
index a77dd07..c3222b2 100644
--- a/boards/z80/ez80/z20x/src/ez80_spi.c
+++ b/boards/z80/ez80/z20x/src/ez80_spi.c
@@ -1,4 +1,4 @@
-/*****************************************************************************
+/****************************************************************************
  * boards/z80/ez80/z20x/src/ez80_spi.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -18,7 +18,7 @@
  *
  ****************************************************************************/
 
-/*****************************************************************************
+/****************************************************************************
  * Included Files
  ****************************************************************************/
 
@@ -30,10 +30,10 @@
 
 #include "chip.h"
 #include "z80_internal.h"
-#include "ez80f91_spi.h"
+#include "ez80_spi.h"
 #include "z20x.h"
 
-/*****************************************************************************
+/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
@@ -41,7 +41,7 @@
  * Then we don't need to Card Detect callback here.
  */
 
-/*****************************************************************************
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -99,7 +99,7 @@ void ez80_spidev_initialize(void)
 #endif
 }
 
-/*****************************************************************************
+/****************************************************************************
  * The external functions, ez80_spiselect, ez80_spistatus, and
  * ez80_spicmddata must be provided by board-specific logic.  These are
  * implementations of the select, status, and cmddata methods of the SPI
diff --git a/boards/z80/ez80/z20x/src/ez80_spimmcsd.c b/boards/z80/ez80/z20x/src/ez80_spimmcsd.c
index 86938c4..2cf01ba 100644
--- a/boards/z80/ez80/z20x/src/ez80_spimmcsd.c
+++ b/boards/z80/ez80/z20x/src/ez80_spimmcsd.c
@@ -1,4 +1,4 @@
-/*****************************************************************************
+/****************************************************************************
  * boards/z80/ez80/z20x/src/ez80_spimmcsd.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -18,7 +18,7 @@
  *
  ****************************************************************************/
 
-/*****************************************************************************
+/****************************************************************************
  * Included Files
  ****************************************************************************/
 
@@ -34,12 +34,12 @@
 #include <nuttx/spi/spi.h>
 
 #include "chip.h"
-#include "ez80f91_spi.h"
+#include "ez80_spi.h"
 #include "z20x.h"
 
 #ifdef HAVE_MMCSD
 
-/*****************************************************************************
+/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
@@ -50,11 +50,11 @@
  * 2. Media Change callbacks are not yet implemented in the SPI driver.
  */
 
-/*****************************************************************************
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
-/*****************************************************************************
+/****************************************************************************
  * Name: ez80_mmcsd_initialize
  *
  * Description:
diff --git a/boards/z80/ez80/z20x/src/ez80_w25.c b/boards/z80/ez80/z20x/src/ez80_w25.c
index e468331..462d064 100644
--- a/boards/z80/ez80/z20x/src/ez80_w25.c
+++ b/boards/z80/ez80/z20x/src/ez80_w25.c
@@ -35,7 +35,7 @@
 #include <nuttx/mtd/mtd.h>
 #include <nuttx/drivers/drivers.h>
 
-#include "ez80f91_spi.h"
+#include "ez80_spi.h"
 #include "z20x.h"
 
 /****************************************************************************
@@ -54,10 +54,6 @@ int ez80_w25_initialize(int minor)
 {
   FAR struct spi_dev_s *spi;
   FAR struct mtd_dev_s *mtd;
-#ifdef CONFIG_Z20X_W25_CHARDEV
-  char blockdev[18];
-  char chardev[12];
-#endif
   int ret;
 
   /* Get the SPI port */
@@ -98,17 +94,12 @@ int ez80_w25_initialize(int minor)
       return ret;
     }
 
-  /* Use the minor number to create device paths */
-
-  snprintf(blockdev, 18, "/dev/mtdblock%d", minor);
-  snprintf(chardev, 12, "/dev/mtd%d", minor);
-
-  /* Now create a character device on the block device */
+  /* Create a character device on the block device */
 
-  ret = bchdev_register(blockdev, chardev, false);
+  ret = bchdev_register(W25_BLOCKDEV, W25_CHARDEV, false);
   if (ret < 0)
     {
-      ferr("ERROR: bchdev_register %s failed: %d\n", chardev, ret);
+      ferr("ERROR: bchdev_register %s failed: %d\n", W25_CHARDEV, ret);
       return ret;
     }
 #endif
diff --git a/boards/z80/ez80/z20x/src/sd_main.c b/boards/z80/ez80/z20x/src/sd_main.c
index 93961cb..7355874 100644
--- a/boards/z80/ez80/z20x/src/sd_main.c
+++ b/boards/z80/ez80/z20x/src/sd_main.c
@@ -44,12 +44,7 @@
 #define MMCSD_MOUNTPT    "/mnt/sdcard"
 #define MMCSD_HEXFILE    "/mnt/sdcard/nuttx.hex"
 
-#define SRAM_START       0x040000
-#define SRAM_SIZE        0x100000
-#define SRAM_END         (SRAM_START + SRAM_SIZE)
-
-#define SRAM_RESET       SRAM_START
-#define SRAM_ENTRY       ((sram_entry_t)SRAM_START)
+#define SRAM_ENTRY       ((sram_entry_t)PROGSTART)
 
 /****************************************************************************
  * Private Types
@@ -115,7 +110,7 @@ int sd_main(int argc, char *argv)
 
   /* Load the HEX image into memory */
 
-  ret = hex2mem(fd, (uint32_t)SRAM_START, (uint32_t)SRAM_END, 0);
+  ret = hex2mem(fd, (uint32_t)PROGSTART, (uint32_t)PROGEND, 0);
   if (ret < 0)
     {
       /* We failed to load the HEX image */
diff --git a/boards/z80/ez80/z20x/src/w25_main.c b/boards/z80/ez80/z20x/src/w25_main.c
new file mode 100644
index 0000000..934b229
--- /dev/null
+++ b/boards/z80/ez80/z20x/src/w25_main.c
@@ -0,0 +1,492 @@
+/****************************************************************************
+ * boards/z80/ez80/z20x/src/w25_main.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <debug.h>
+#include <hex2bin.h>
+
+#include <nuttx/streams.h>
+#include <arch/irq.h>
+
+#include "z20x.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifndef HAVE_SPIFLASH
+#  error The W25 Serial FLASH is not available
+#endif
+
+#ifndef CONFIG_Z20X_W25_CHARDEV
+#  error CONFIG_Z20X_W25_CHARDEV must be selected
+#endif
+
+#if !defined(CONFIG_Z20X_W25_PROGSIZE) || CONFIG_Z20X_W25_PROGSIZE < 128
+#  error Large CONFIG_Z20X_W25_PROGSIZE must be selected
+#endif
+
+#define IOBUFFER_SIZE   512
+#define PROG_MAGIC      0xfedbad
+
+#define SRAM_ENTRY      ((sram_entry_t)PROGSTART)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef CODE void (*sram_entry_t)(void);
+
+/* This is the header places at the beginning of the binary data in FLASH */
+
+struct prog_header_s
+{
+  uint24_t magic;  /* Valid if PROG_MAGIC */
+  uint24_t crc;    /* Last 24-bits of CRC32 */
+  uint24_t len;    /* Binary length */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: w25_read_hex
+ *
+ * Description:
+ *   Read and parse a HEX data stream into RAM.  HEX data will be read from
+ *   stdin and written to the program area reserved in RAM, that is, the
+ *   address range from PROGSTART to PROGREND.
+ *
+ ****************************************************************************/
+
+static int w25_read_hex(FAR uint24_t *len)
+{
+  struct lib_rawinstream_s rawinstream;
+  struct lib_memsostream_s memoutstream;
+  int fd;
+  int ret;
+
+  /* Open the W25 device for writing */
+
+  fd = open(W25_CHARDEV, O_WRONLY);
+  if (fd < 0)
+    {
+      ret = -get_errno();
+      fprintf(stderr, "ERROR: Failed to open %s: %d\n", W25_CHARDEV, ret);
+      return ret;
+    }
+
+  /* Wrap stdin as an IN stream that can get the HEX data over the serial port */
+
+  lib_rawinstream(&rawinstream, 0);
+
+  /* Wrap the memory area used to hold the program as a seek-able OUT stream in
+   * which we can buffer the binary data.
+   */
+
+  lib_memsostream(&memoutstream, (FAR char *)PROGSTART, PROGSIZE);
+
+  /* We are ready to load the Intel HEX stream into external SRAM.
+   *
+   * Hmm.. With no hardware handshake, there is a possibility of data loss
+   * to overrunning incoming data buffer.  So far I have not seen this at
+   * 115200 8N1, but still it is a possibility.
+   */
+
+  printf("Send Intel HEX file now\n");
+  fflush(stdout);
+
+  ret = hex2bin(&rawinstream.public, &memoutstream.public,
+                (uint32_t)PROGSTART, (uint32_t)(PROGSTART + PROGSIZE),
+                0);
+
+  close(fd);
+  if (ret < 0)
+    {
+      /* We failed the load */
+
+      fprintf(stderr, "ERROR: Intel HEX file load failed: %d\n", ret);
+      return ret;
+    }
+
+  printf("Successfully loaded the Intel HEX file into memory...\n");
+  *len = memoutstream.public.nput;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: w25_write
+ *
+ * Description:
+ *   Write to the open file descriptor, handling failures and repeated
+ *   write operations as necessary.
+ *
+ ****************************************************************************/
+
+static int w25_write(int fd, FAR const void *src, size_t len)
+{
+  ssize_t remaining = len;
+  ssize_t nwritten;
+
+  do
+    {
+      nwritten = write(fd, src, remaining);
+      if (nwritten <= 0)
+        {
+          int errcode = get_errno();
+          if (errno != EINTR)
+            {
+              fprintf(stderr, "ERROR: Write failed: %d\n", errcode);
+              return -errcode;
+            }
+        }
+      else
+        {
+          remaining -= nwritten;
+          src += nwritten;
+        }
+    }
+  while (remaining > 0);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: w25_write_binary
+ *
+ * Description:
+ *   Write a program header followed by the binary data beginning at address
+ *   PROGSTART into the first partition of the w25 FLASH memory.
+ *
+ ****************************************************************************/
+
+static int w25_write_binary(FAR const struct prog_header_s *hdr)
+{
+  int fd;
+  int ret;
+
+  /* Open the W25 device for writing */
+
+  fd = open(W25_CHARDEV, O_WRONLY);
+  if (fd < 0)
+    {
+      ret = -get_errno();
+      fprintf(stderr, "ERROR: Failed to open %s: %d\n", W25_CHARDEV, ret);
+      return ret;
+    }
+
+  /* Write the hdr to the W25 */
+
+  ret = w25_write(fd, hdr, sizeof(struct prog_header_s));
+  if (fd < 0)
+    {
+      ret = -get_errno();
+      fprintf(stderr, "ERROR: Failed write program header: %d\n", ret);
+      goto errout;
+    }
+
+  printf("Writing %lu bytes to the W25 Serial FLASH\n", (unsigned long)hdr->len);
+
+  ret = w25_write(fd, (FAR const void *)PROGSTART, hdr->len);
+  if (ret < 0)
+    {
+      ret = -get_errno();
+      fprintf(stderr, "ERROR: Failed write program header: %d\n", ret);
+    }
+
+errout:
+  close(fd);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: w25_read
+ *
+ * Description:
+ *   Read from the open file descriptor, handling errors as retries as
+ *   necessary.
+ *
+ ****************************************************************************/
+
+static int w25_read(int fd, FAR void *dest, size_t len)
+{
+  ssize_t remaining = len;
+  ssize_t nread;
+
+  do
+    {
+      nread = read(fd, dest, remaining);
+      if (nread <= 0)
+        {
+          int errcode = get_errno();
+          if (errno != EINTR)
+            {
+              fprintf(stderr, "ERROR: Read failed: %d\n", errcode);
+              close(fd);
+              return -errcode;
+            }
+        }
+
+      remaining -= nread;
+      dest += nread;
+    }
+  while (remaining > 0);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: w25_read_binary
+ *
+ * Description:
+ *   Read the program in the first partition of the W25 part into memory
+ *   at PROGSTART.
+ *
+ ****************************************************************************/
+
+static int w25_read_binary(FAR struct prog_header_s *hdr)
+{
+  int fd;
+  int ret;
+
+  /* Open the W25 device for reading */
+
+  fd = open(W25_CHARDEV, O_RDONLY);
+  if (fd < 0)
+    {
+      ret = -get_errno();
+      fprintf(stderr, "ERROR: Failed to open %s: %d\n", W25_CHARDEV, ret);
+      return ret;
+    }
+
+  /* Read the header at the beginning of the partition */
+
+  ret = w25_read(fd, hdr, sizeof(hdr));
+  if (ret < 0)
+    {
+      ret = -get_errno();
+      fprintf(stderr, "ERROR: Failed read program header: %d\n", ret);
+      goto errout;
+    }
+
+  /* Check for a valid program header */
+
+  if (hdr->magic != PROG_MAGIC)
+    {
+      fprintf(stderr, "ERROR: No program in FLASH\n");
+      ret = -ENOENT;
+      goto errout;
+    }
+
+  if (hdr->len != PROGSIZE)
+    {
+      fprintf(stderr, "ERROR: Program too big\n");
+      ret = -E2BIG;
+      goto errout;
+    }
+
+  /* Read the program binary */
+
+  ret = w25_read(fd, (FAR void *)PROGSTART, hdr->len);
+  if (ret < 0)
+    {
+      ret = -get_errno();
+      fprintf(stderr, "ERROR: Failed read program header: %d\n", ret);
+    }
+
+errout:
+  close(fd);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: w25_crc24
+ *
+ * Description:
+ *   Calculate a CRC24 checksum on the data loaded into memory starting at
+ *   PROGSTART.
+ *
+ ****************************************************************************/
+
+uint24_t w25_crc24(uint32_t len)
+{
+  FAR const uint8_t *src = (FAR const uint8_t *)PROGSTART;
+  uint32_t crc = 0;
+  int i;
+  int j;
+
+  for (i = 0; i < len; i++)
+    {
+      uint8_t val = *src++;
+      crc ^= (uint32_t)val << 16;
+
+      for (j = 0; j < 8; j++)
+        {
+          crc <<= 1;
+          if ((crc & 0x1000000) != 0)
+            {
+              crc ^= 0x1864cfb;
+            }
+        }
+    }
+
+  return (uint24_t)crc;
+}
+
+/****************************************************************************
+ * Name: w25_read_verify
+ *
+ * Description:
+ *   Verify that the program in the first partition of the W25 part matches
+ *   the program in memory at address PROGSTART.
+ *
+ ****************************************************************************/
+
+static int w25_read_verify(void)
+{
+  struct prog_header_s hdr;
+  uint24_t crc;
+  int fd;
+  int ret;
+
+  /* Read the program image into memory */
+
+  ret = w25_read_binary(&hdr);
+  if (ret < 0)
+    {
+      ret = -get_errno();
+      fprintf(stderr, "ERROR: Failed to read binary: %d\n", ret);
+      return ret;
+    }
+
+  printf("Verifying %lu bytes in the W25 Serial FLASH\n",
+         (unsigned long)hdr.len);
+
+  /* Compare CRCs */
+
+  crc = w25_crc24(hdr.len);
+  if (crc == hdr.crc)
+    {
+      printf("Successfully verified %lu bytes in the W25 Serial FLASH\n",
+             (unsigned long)hdr.len);
+    }
+  else
+    {
+      fprintf(stderr, "ERROR: CRC check failed\n");
+      return -EINVAL;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: w25_main
+ *
+ * Description:
+ *   w25_main is a tiny program that runs in ISRAM.  w25_main will
+ *   configure DRAM and the W25 serial FLASH, present a prompt, and load
+ *   an Intel HEX file into the W25 serial FLASH (after first buffering
+ *   the binary data into memory).  On re-boot, the program loaded into
+ *   the W25 FLASH should then execute.
+ *
+ *   On entry:
+ *   - SDRAM has already been initialized (we are using it for .bss!)
+ *   - SPI0 chip select has already been configured.
+ *
+ ****************************************************************************/
+
+int w25_main(int argc, char *argv)
+{
+  struct prog_header_s hdr;
+  int ret;
+
+#ifndef CONFIG_BOARD_LATE_INITIALIZE
+  /* Initialize the board.  We can do this with a direct call because we are
+   * a kernel thread.
+   */
+
+  ret = ez80_bringup();
+  if (ret < 0)
+    {
+      fprintf(stderr, "ERROR: Failed initialize system: %d\n", ret);
+      return EXIT_FAILURE;
+    }
+#endif
+
+  for (; ; )
+    {
+      /* Read the HEX data into RAM */
+
+      memset(&hdr, 0, sizeof(struct prog_header_s));
+      hdr.magic = PROG_MAGIC;
+
+      ret = w25_read_hex(&hdr.len);
+      if (ret < 0)
+        {
+          fprintf(stderr, "ERROR: Failed to load HEX: %d\n", ret);
+          return EXIT_FAILURE;
+        }
+
+      /* Calculate a CRC24 checksum */
+
+      hdr.crc = w25_crc24(hdr.len);
+
+      /* The HEX file load was successful, write the data to FLASH */
+
+      ret = w25_write_binary(&hdr);
+      if (ret < 0)
+        {
+          fprintf(stderr, "ERROR: Failed to write to W25: %d\n", ret);
+          return EXIT_FAILURE;
+        }
+
+      /* Now verify that the image in memory and the image in FLASH are
+       * truly the same.
+       */
+
+      ret = w25_read_verify();
+      if (ret < 0)
+        {
+          fprintf(stderr, "ERROR: Failed to verify program: %d\n", ret);
+          return EXIT_FAILURE;
+        }
+    }
+
+  return EXIT_SUCCESS;
+}
diff --git a/boards/z80/ez80/z20x/src/z20x.h b/boards/z80/ez80/z20x/src/z20x.h
index 1ca9052..e529745 100644
--- a/boards/z80/ez80/z20x/src/z20x.h
+++ b/boards/z80/ez80/z20x/src/z20x.h
@@ -86,6 +86,45 @@
  * Chip select 3 is not used
  */
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* RAM Memory map
+ *
+ * 040000              Beginning of RAM
+ * 040000 _vecstart    Beginning of Vector information.  Used to hand off
+ *                     to RAM-based handlers for interrupts caught by
+ *                     FLASH interrupt vectors. 1Kb is set aside for RAM-
+ *                     based interrupt handling information.
+ * 040400 _loaderstart Start of RAM used exclusively by the bootloader.
+ *                     This memory region an be recovered by the RAM-based
+ *                     program.
+ * 04ffff _loaderend
+ * 050000 _progstart   Start of CODE for the RAM-based program.  The
+ *                     program can freely use the memory region from
+ *                     050000-0bffff and can recover the memory for
+ *                     40400-04ffff for heap usage.
+ * 0bffff _progend     End of RAM
+ */
+
+extern unsigned long _vecstart;
+#define VECSTART     ((uintptr_t)&_vecstart)
+
+extern unsigned long _loaderstart;
+#define LOADERSTART  ((uintptr_t)&_loaderstart)
+
+extern unsigned long _loaderend;
+#define LOADEREND    ((uintptr_t)&_loaderend)
+
+extern unsigned long _progstart;
+#define PROGSTART    ((uintptr_t)&_progstart)
+
+extern unsigned long _progend;
+#define PROGEND      ((uintptr_t)&_progend)
+
+#define PROGSIZE     (PROGEND - PROGSTART + 1)
+
 /* LED and port emulation memory register addresses */
 
 /* GPIO data bit definitions */
@@ -99,8 +138,20 @@
 #define EZ80_GPIOD6       (1 << 6)
 #define EZ80_GPIOD7       (1 << 7)
 
+/* Winbond W25 SPI FLASH */
+
+#ifndef CONFIG_Z20X_W25_MINOR
+#  define CONFIG_Z20X_W25_MINOR 0
+#endif
+
+#define __STR(s) #s
+#define __XSTR(s) __STR(s)
+
+#define W25_CHARDEV  "/dev/mtd" __XSTR(CONFIG_Z20X_W25_MINOR)
+#define W25_BLOCKDEV "/dev/mtdblock" __XSTR(CONFIG_Z20X_W25_MINOR)
+
 /****************************************************************************
- * Public Functions
+ * Public Function Prototypes
  ****************************************************************************/
 
 #undef EXTERN
@@ -128,7 +179,7 @@ extern "C"
 
 int ez80_bringup(void);
 
-/*****************************************************************************
+/****************************************************************************
  * Name: ez80_mmcsd_initialize
  *
  * Description: