Updates for zOS running on the ZPU Evo on a Sharp MZ-700, tzflupd for programming the K64F FlashRAM in-situ

This commit is contained in:
Philip Smart
2021-02-21 23:18:27 +00:00
parent d8d7ffb200
commit f266281580
57 changed files with 390158 additions and 358960 deletions

11
.gitignore vendored
View File

@@ -74,3 +74,14 @@ zputa/*.ii
zputa/*.s
zOS/main.save
/tzio/
.dobuild
SD/
frdm/
frdmk64f_usb_msd_host_bootloader_mcux.zip
frdmk64f_usb_msd_host_bootloader_mcux/
getopt_long.c
libraries/include/optparse.h
minicom.cap
startup/app_zos_zpu.tmpl2
zOS/main.bak

View File

@@ -64,7 +64,7 @@ MISC_SUBDIRS := help time
APP_SUBDIRS := tbasic mbasic kilo ed
ifeq ($(__K64F__),1)
ifeq ($(__TRANZPUTER__),1)
TZPU_SUBDIRS := tzpu tzload tzdump tzclear tzclk tzreset tzio
TZPU_SUBDIRS := tzpu tzload tzdump tzclear tzclk tzreset tzio tzflupd
endif
else
TZPU_SUBDIRS :=

View File

@@ -101,6 +101,7 @@ FATFS_DIR = $(CURDIR)/../../common/FatFS
DHRY_DIR = $(CURDIR)/../../common/Dhrystone
COREMARK_DIR = $(CURDIR)/../../common/CoreMark
UMM_DIR = $(CURDIR)/../../common/umm
TEENSY_DIR = $(CURDIR)/../../teensy3
INCLUDE_DIR = $(CURDIR)/../../include
LIB_DIR = $(CURDIR)/../../libraries/lib
LIB_INCLUDE_DIR= $(CURDIR)/../../libraries/include
@@ -110,7 +111,11 @@ APP_INCLUDE_DIR= $(CURDIR)/../include
BUILD_DIR = $(abspath $(CURDIR)/build)
# Startup code.
CRT0_ASM_SRC = $(STARTUP_DIR)/app_k64f_crt0.s
ifeq (__TZFLUPD__,$(findstring __TZFLUPD__,$(CFLAGS)))
CRT0_ASM_SRC = $(STARTUP_DIR)/app_k64f_hwctl_crt0.s
else
CRT0_ASM_SRC = $(STARTUP_DIR)/app_k64f_crt0.s
endif
# Memory management code. Bring in the UMM library if stdlib isnt being used.
#ifeq (-nostdlib,$(findstring -nostdlib,$(LDFLAGS)))
@@ -124,14 +129,20 @@ TEENSY3_C_SRC = #$(wildcard $(COREPATH)/*.c)
TEENSY3_CPP_SRC= #$(wildcard $(COREPATH)/*.cpp)
# Common modules needed for this app.
COMMON_SRC = #../common/sysutils.c #../common/sbrk.c
ifeq (__TZFLUPD__,$(findstring __TZFLUPD__,$(CFLAGS)))
COMMON_C_SRC = $(FATFS_DIR)/ff.c $(FATFS_DIR)/ffunicode.c $(TEENSY_DIR)/nonstd.c
COMMON_CPP_SRC = $(FATFS_DIR)/sdmmc_k64f.cpp $(TEENSY_DIR)/NXP_SDHC.cpp
else
COMMON_C_SRC = #../common/sysutils.c #../common/sbrk.c
COMMON_CPP_SRC =
endif
# Application being built.
MAIN_PRJ_APP = $(APP_NAME)
MAIN_SRC = $(APP_NAME).c
# Define the sources and what they compile from->to.
SOURCES := $(CRT0_ASM_SRC:.s=.o) $(COMMON_SRC:.c=.o) $(UMM_C_SRC:.c=.o) $(CORE_SRC:.c=.o) $(C_FILES:.c=.o) $(CPP_FILES:.cpp=.o) $(TEENSY3_C_SRC:.c=.o) $(TEENSY3_CPP_SRC:.cpp=.o) $(DHRY_SRC:.c=.o) $(COREMARK_SRC:.c=.o) $(APP_C_SRC:.c=.o) $(APP_CPP_SRC:.cpp=.o) $(MAIN_SRC:.c=.o)
SOURCES := $(CRT0_ASM_SRC:.s=.o) $(COMMON_C_SRC:.c=.o) $(COMMON_CPP_SRC:.cpp=.o) $(UMM_C_SRC:.c=.o) $(CORE_SRC:.c=.o) $(C_FILES:.c=.o) $(CPP_FILES:.cpp=.o) $(TEENSY3_C_SRC:.c=.o) $(TEENSY3_CPP_SRC:.cpp=.o) $(DHRY_SRC:.c=.o) $(COREMARK_SRC:.c=.o) $(APP_C_SRC:.c=.o) $(APP_CPP_SRC:.cpp=.o) $(MAIN_SRC:.c=.o)
OBJS := $(foreach src,$(SOURCES), $(BUILD_DIR)/$(src))
# CPPFLAGS = compiler options for C and C++

3527
apps/common/fsl_flash.c Normal file

File diff suppressed because it is too large Load Diff

12762
apps/include/MK64F12.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1373
apps/include/cmsis_gcc.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
/**************************************************************************//**
* @file core_cmFunc.h
* @brief CMSIS Cortex-M Core Function Access Header File
* @version V4.30
* @date 20. October 2015
******************************************************************************/
/* Copyright (c) 2009 - 2015 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------*/
#if defined ( __ICCARM__ )
#pragma system_include /* treat file as system include file for MISRA check */
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#pragma clang system_header /* treat file as system include file */
#endif
#ifndef __CORE_CMFUNC_H
#define __CORE_CMFUNC_H
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
/*------------------ RealView Compiler -----------------*/
#if defined ( __CC_ARM )
#include "cmsis_armcc.h"
/*------------------ ARM Compiler V6 -------------------*/
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#include "cmsis_armcc_V6.h"
/*------------------ GNU Compiler ----------------------*/
#elif defined ( __GNUC__ )
// #include "cmsis_gcc.h"
/*------------------ ICC Compiler ----------------------*/
#elif defined ( __ICCARM__ )
#include <cmsis_iar.h>
/*------------------ TI CCS Compiler -------------------*/
#elif defined ( __TMS470__ )
#include <cmsis_ccs.h>
/*------------------ TASKING Compiler ------------------*/
#elif defined ( __TASKING__ )
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
/*------------------ COSMIC Compiler -------------------*/
#elif defined ( __CSMC__ )
#include <cmsis_csm.h>
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H */

1572
apps/include/fsl_clock.h Normal file

File diff suppressed because it is too large Load Diff

516
apps/include/fsl_common.h Normal file
View File

@@ -0,0 +1,516 @@
/*
* The Clear BSD License
* Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* o Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _FSL_COMMON_H_
#define _FSL_COMMON_H_
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#if defined(__ICCARM__)
#include <stddef.h>
#endif
#include "fsl_device_registers.h"
/*!
* @addtogroup ksdk_common
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @brief Construct a status code value from a group and code number. */
#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
/*! @brief Construct the version number for drivers. */
#define MAKE_VERSION(major, minor, bugfix) (((major) << 16) | ((minor) << 8) | (bugfix))
/*! @name Driver version */
/*@{*/
/*! @brief common driver version 2.0.0. */
#define FSL_COMMON_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/* Debug console type definition. */
#define DEBUG_CONSOLE_DEVICE_TYPE_NONE 0U /*!< No debug console. */
#define DEBUG_CONSOLE_DEVICE_TYPE_UART 1U /*!< Debug console base on UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPUART 2U /*!< Debug console base on LPUART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_LPSCI 3U /*!< Debug console base on LPSCI. */
#define DEBUG_CONSOLE_DEVICE_TYPE_USBCDC 4U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_FLEXCOMM 5U /*!< Debug console base on USBCDC. */
#define DEBUG_CONSOLE_DEVICE_TYPE_IUART 6U /*!< Debug console base on i.MX UART. */
#define DEBUG_CONSOLE_DEVICE_TYPE_VUSART 7U /*!< Debug console base on LPC_USART. */
/*! @brief Status group numbers. */
enum _status_groups
{
kStatusGroup_Generic = 0, /*!< Group number for generic status codes. */
kStatusGroup_FLASH = 1, /*!< Group number for FLASH status codes. */
kStatusGroup_LPSPI = 4, /*!< Group number for LPSPI status codes. */
kStatusGroup_FLEXIO_SPI = 5, /*!< Group number for FLEXIO SPI status codes. */
kStatusGroup_DSPI = 6, /*!< Group number for DSPI status codes. */
kStatusGroup_FLEXIO_UART = 7, /*!< Group number for FLEXIO UART status codes. */
kStatusGroup_FLEXIO_I2C = 8, /*!< Group number for FLEXIO I2C status codes. */
kStatusGroup_LPI2C = 9, /*!< Group number for LPI2C status codes. */
kStatusGroup_UART = 10, /*!< Group number for UART status codes. */
kStatusGroup_I2C = 11, /*!< Group number for UART status codes. */
kStatusGroup_LPSCI = 12, /*!< Group number for LPSCI status codes. */
kStatusGroup_LPUART = 13, /*!< Group number for LPUART status codes. */
kStatusGroup_SPI = 14, /*!< Group number for SPI status code.*/
kStatusGroup_XRDC = 15, /*!< Group number for XRDC status code.*/
kStatusGroup_SEMA42 = 16, /*!< Group number for SEMA42 status code.*/
kStatusGroup_SDHC = 17, /*!< Group number for SDHC status code */
kStatusGroup_SDMMC = 18, /*!< Group number for SDMMC status code */
kStatusGroup_SAI = 19, /*!< Group number for SAI status code */
kStatusGroup_MCG = 20, /*!< Group number for MCG status codes. */
kStatusGroup_SCG = 21, /*!< Group number for SCG status codes. */
kStatusGroup_SDSPI = 22, /*!< Group number for SDSPI status codes. */
kStatusGroup_FLEXIO_I2S = 23, /*!< Group number for FLEXIO I2S status codes */
kStatusGroup_FLEXIO_MCULCD = 24, /*!< Group number for FLEXIO LCD status codes */
kStatusGroup_FLASHIAP = 25, /*!< Group number for FLASHIAP status codes */
kStatusGroup_FLEXCOMM_I2C = 26, /*!< Group number for FLEXCOMM I2C status codes */
kStatusGroup_I2S = 27, /*!< Group number for I2S status codes */
kStatusGroup_IUART = 28, /*!< Group number for IUART status codes */
kStatusGroup_CSI = 29, /*!< Group number for CSI status codes */
kStatusGroup_MIPI_DSI = 30, /*!< Group number for MIPI DSI status codes */
kStatusGroup_SDRAMC = 35, /*!< Group number for SDRAMC status codes. */
kStatusGroup_POWER = 39, /*!< Group number for POWER status codes. */
kStatusGroup_ENET = 40, /*!< Group number for ENET status codes. */
kStatusGroup_PHY = 41, /*!< Group number for PHY status codes. */
kStatusGroup_TRGMUX = 42, /*!< Group number for TRGMUX status codes. */
kStatusGroup_SMARTCARD = 43, /*!< Group number for SMARTCARD status codes. */
kStatusGroup_LMEM = 44, /*!< Group number for LMEM status codes. */
kStatusGroup_QSPI = 45, /*!< Group number for QSPI status codes. */
kStatusGroup_DMA = 50, /*!< Group number for DMA status codes. */
kStatusGroup_EDMA = 51, /*!< Group number for EDMA status codes. */
kStatusGroup_DMAMGR = 52, /*!< Group number for DMAMGR status codes. */
kStatusGroup_FLEXCAN = 53, /*!< Group number for FlexCAN status codes. */
kStatusGroup_LTC = 54, /*!< Group number for LTC status codes. */
kStatusGroup_FLEXIO_CAMERA = 55, /*!< Group number for FLEXIO CAMERA status codes. */
kStatusGroup_LPC_SPI = 56, /*!< Group number for LPC_SPI status codes. */
kStatusGroup_LPC_USART = 57, /*!< Group number for LPC_USART status codes. */
kStatusGroup_DMIC = 58, /*!< Group number for DMIC status codes. */
kStatusGroup_SDIF = 59, /*!< Group number for SDIF status codes.*/
kStatusGroup_SPIFI = 60, /*!< Group number for SPIFI status codes. */
kStatusGroup_OTP = 61, /*!< Group number for OTP status codes. */
kStatusGroup_MCAN = 62, /*!< Group number for MCAN status codes. */
kStatusGroup_CAAM = 63, /*!< Group number for CAAM status codes. */
kStatusGroup_ECSPI = 64, /*!< Group number for ECSPI status codes. */
kStatusGroup_USDHC = 65, /*!< Group number for USDHC status codes.*/
kStatusGroup_LPC_I2C = 66, /*!< Group number for LPC_I2C status codes.*/
kStatusGroup_DCP = 67, /*!< Group number for DCP status codes.*/
kStatusGroup_MSCAN = 68, /*!< Group number for MSCAN status codes.*/
kStatusGroup_ESAI = 69, /*!< Group number for ESAI status codes. */
kStatusGroup_FLEXSPI = 70, /*!< Group number for FLEXSPI status codes. */
kStatusGroup_MMDC = 71, /*!< Group number for MMDC status codes. */
kStatusGroup_MICFIL = 72, /*!< Group number for MIC status codes. */
kStatusGroup_SDMA = 73, /*!< Group number for SDMA status codes. */
kStatusGroup_ICS = 74, /*!< Group number for ICS status codes. */
kStatusGroup_SPDIF = 75, /*!< Group number for SPDIF status codes. */
kStatusGroup_NOTIFIER = 98, /*!< Group number for NOTIFIER status codes. */
kStatusGroup_DebugConsole = 99, /*!< Group number for debug console status codes. */
kStatusGroup_SEMC = 100, /*!< Group number for SEMC status codes. */
kStatusGroup_ApplicationRangeStart = 101, /*!< Starting number for application groups. */
};
/*! @brief Generic status return codes. */
enum _generic_status
{
kStatus_Success = MAKE_STATUS(kStatusGroup_Generic, 0),
kStatus_Fail = MAKE_STATUS(kStatusGroup_Generic, 1),
kStatus_ReadOnly = MAKE_STATUS(kStatusGroup_Generic, 2),
kStatus_OutOfRange = MAKE_STATUS(kStatusGroup_Generic, 3),
kStatus_InvalidArgument = MAKE_STATUS(kStatusGroup_Generic, 4),
kStatus_Timeout = MAKE_STATUS(kStatusGroup_Generic, 5),
kStatus_NoTransferInProgress = MAKE_STATUS(kStatusGroup_Generic, 6),
};
/*! @brief Type used for all status and error return values. */
typedef int32_t status_t;
/*
* The fsl_clock.h is included here because it needs MAKE_VERSION/MAKE_STATUS/status_t
* defined in previous of this file.
*/
#include "fsl_clock.h"
/*
* Chip level peripheral reset API, for MCUs that implement peripheral reset control external to a peripheral
*/
#if ((defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0)) || \
(defined(FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT) && (FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT > 0)))
#include "fsl_reset.h"
#endif
/*! @name Min/max macros */
/* @{ */
#if !defined(MIN)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#if !defined(MAX)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
/* @} */
/*! @brief Computes the number of elements in an array. */
#if !defined(ARRAY_SIZE)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
/*! @name UINT16_MAX/UINT32_MAX value */
/* @{ */
#if !defined(UINT16_MAX)
#define UINT16_MAX ((uint16_t)-1)
#endif
#if !defined(UINT32_MAX)
#define UINT32_MAX ((uint32_t)-1)
#endif
/* @} */
/*! @name Timer utilities */
/* @{ */
/*! Macro to convert a microsecond period to raw count value */
#define USEC_TO_COUNT(us, clockFreqInHz) (uint64_t)((uint64_t)us * clockFreqInHz / 1000000U)
/*! Macro to convert a raw count value to microsecond */
#define COUNT_TO_USEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000000U / clockFreqInHz)
/*! Macro to convert a millisecond period to raw count value */
#define MSEC_TO_COUNT(ms, clockFreqInHz) (uint64_t)((uint64_t)ms * clockFreqInHz / 1000U)
/*! Macro to convert a raw count value to millisecond */
#define COUNT_TO_MSEC(count, clockFreqInHz) (uint64_t)((uint64_t)count * 1000U / clockFreqInHz)
/* @} */
/*! @name Alignment variable definition macros */
/* @{ */
#if (defined(__ICCARM__))
/**
* Workaround to disable MISRA C message suppress warnings for IAR compiler.
* http://supp.iar.com/Support/?note=24725
*/
_Pragma("diag_suppress=Pm120")
#define SDK_PRAGMA(x) _Pragma(#x)
_Pragma("diag_error=Pm120")
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) SDK_PRAGMA(data_alignment = FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) var
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) SDK_PRAGMA(data_alignment = FSL_FEATURE_L2CACHE_LINESIZE_BYTE) var
#endif
#elif defined(__ARMCC_VERSION)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) __align(alignbytes) var
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) __align(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) var
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) __align(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) var
#endif
#elif defined(__GNUC__)
/*! Macro to define a variable with alignbytes alignment */
#define SDK_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
/*! Macro to define a variable with L1 d-cache line size alignment */
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) var __attribute__((aligned(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)))
#endif
/*! Macro to define a variable with L2 cache line size alignment */
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) var __attribute__((aligned(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)))
#endif
#else
#error Toolchain not supported
#define SDK_ALIGN(var, alignbytes) var
#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
#define SDK_L1DCACHE_ALIGN(var) var
#endif
#if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
#define SDK_L2CACHE_ALIGN(var) var
#endif
#endif
/*! Macro to change a value to a given size aligned value */
#define SDK_SIZEALIGN(var, alignbytes) \
((unsigned int)((var) + ((alignbytes)-1)) & (unsigned int)(~(unsigned int)((alignbytes)-1)))
/* @} */
/*! @name Non-cacheable region definition macros */
/* For initialized non-zero non-cacheable variables, please using "AT_NONCACHEABLE_SECTION_INIT(var) ={xx};" or
* "AT_NONCACHEABLE_SECTION_ALIGN_INIT(var) ={xx};" in your projects to define them, for zero-inited non-cacheable variables,
* please using "AT_NONCACHEABLE_SECTION(var);" or "AT_NONCACHEABLE_SECTION_ALIGN(var);" to define them, these zero-inited variables
* will be initialized to zero in system startup.
*/
/* @{ */
#if (defined(__ICCARM__))
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION(var) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable"
#define AT_NONCACHEABLE_SECTION_INIT(var) var @"NonCacheable.init"
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var @"NonCacheable.init"
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) SDK_PRAGMA(data_alignment = alignbytes) var
#endif
#elif(defined(__ARMCC_VERSION))
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable"), zero_init)) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable"), zero_init)) __align(alignbytes) var
#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
__attribute__((section("NonCacheable.init"))) __align(alignbytes) var
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) __align(alignbytes) var
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) __align(alignbytes) var
#endif
#elif(defined(__GNUC__))
/* For GCC, when the non-cacheable section is required, please define "__STARTUP_INITIALIZE_NONCACHEDATA"
* in your projects to make sure the non-cacheable section variables will be initialized in system startup.
*/
#if defined(FSL_FEATURE_L1ICACHE_LINESIZE_BYTE)
#define AT_NONCACHEABLE_SECTION_INIT(var) __attribute__((section("NonCacheable.init"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) \
__attribute__((section("NonCacheable.init"))) var __attribute__((aligned(alignbytes)))
#define AT_NONCACHEABLE_SECTION(var) __attribute__((section("NonCacheable,\"aw\",%nobits @"))) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) \
__attribute__((section("NonCacheable,\"aw\",%nobits @"))) var __attribute__((aligned(alignbytes)))
#else
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var __attribute__((aligned(alignbytes)))
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) var __attribute__((aligned(alignbytes)))
#endif
#else
#error Toolchain not supported.
#define AT_NONCACHEABLE_SECTION(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN(var, alignbytes) var
#define AT_NONCACHEABLE_SECTION_INIT(var) var
#define AT_NONCACHEABLE_SECTION_ALIGN_INIT(var, alignbytes) var
#endif
/* @} */
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C"
{
#endif
/*!
* @brief Enable specific interrupt.
*
* Enable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only enables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt enabled successfully
* @retval kStatus_Fail Failed to enable the interrupt
*/
static inline status_t EnableIRQ(IRQn_Type interrupt)
{
if (NotAvail_IRQn == interrupt)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
return kStatus_Fail;
}
#endif
#if defined(__GIC_PRIO_BITS)
GIC_EnableIRQ(interrupt);
#else
NVIC_EnableIRQ(interrupt);
#endif
return kStatus_Success;
}
/*!
* @brief Disable specific interrupt.
*
* Disable LEVEL1 interrupt. For some devices, there might be multiple interrupt
* levels. For example, there are NVIC and intmux. Here the interrupts connected
* to NVIC are the LEVEL1 interrupts, because they are routed to the core directly.
* The interrupts connected to intmux are the LEVEL2 interrupts, they are routed
* to NVIC first then routed to core.
*
* This function only disables the LEVEL1 interrupts. The number of LEVEL1 interrupts
* is indicated by the feature macro FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS.
*
* @param interrupt The IRQ number.
* @retval kStatus_Success Interrupt disabled successfully
* @retval kStatus_Fail Failed to disable the interrupt
*/
static inline status_t DisableIRQ(IRQn_Type interrupt)
{
if (NotAvail_IRQn == interrupt)
{
return kStatus_Fail;
}
#if defined(FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS) && (FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS > 0)
if (interrupt >= FSL_FEATURE_NUMBER_OF_LEVEL1_INT_VECTORS)
{
return kStatus_Fail;
}
#endif
#if defined(__GIC_PRIO_BITS)
GIC_DisableIRQ(interrupt);
#else
NVIC_DisableIRQ(interrupt);
#endif
return kStatus_Success;
}
/*!
* @brief Disable the global IRQ
*
* Disable the global interrupt and return the current primask register. User is required to provided the primask
* register for the EnableGlobalIRQ().
*
* @return Current primask value.
*/
static inline uint32_t DisableGlobalIRQ(void)
{
#if defined(CPSR_I_Msk)
uint32_t cpsr = __get_CPSR() & CPSR_I_Msk;
__disable_irq();
return cpsr;
#else
uint32_t regPrimask = __get_PRIMASK();
__disable_irq();
return regPrimask;
#endif
}
/*!
* @brief Enaable the global IRQ
*
* Set the primask register with the provided primask value but not just enable the primask. The idea is for the
* convinience of integration of RTOS. some RTOS get its own management mechanism of primask. User is required to
* use the EnableGlobalIRQ() and DisableGlobalIRQ() in pair.
*
* @param primask value of primask register to be restored. The primask value is supposed to be provided by the
* DisableGlobalIRQ().
*/
static inline void EnableGlobalIRQ(uint32_t primask)
{
#if defined(CPSR_I_Msk)
__set_CPSR((__get_CPSR() & ~CPSR_I_Msk) | primask);
#else
__set_PRIMASK(primask);
#endif
}
#if defined(ENABLE_RAM_VECTOR_TABLE)
/*!
* @brief install IRQ handler
*
* @param irq IRQ number
* @param irqHandler IRQ handler address
* @return The old IRQ handler address
*/
uint32_t InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler);
#endif /* ENABLE_RAM_VECTOR_TABLE. */
#if (defined(FSL_FEATURE_SOC_SYSCON_COUNT) && (FSL_FEATURE_SOC_SYSCON_COUNT > 0))
/*!
* @brief Enable specific interrupt for wake-up from deep-sleep mode.
*
* Enable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also enables the interrupt in the NVIC (EnableIRQ() is called internally).
*
* @param interrupt The IRQ number.
*/
void EnableDeepSleepIRQ(IRQn_Type interrupt);
/*!
* @brief Disable specific interrupt for wake-up from deep-sleep mode.
*
* Disable the interrupt for wake-up from deep sleep mode.
* Some interrupts are typically used in sleep mode only and will not occur during
* deep-sleep mode because relevant clocks are stopped. However, it is possible to enable
* those clocks (significantly increasing power consumption in the reduced power mode),
* making these wake-ups possible.
*
* @note This function also disables the interrupt in the NVIC (DisableIRQ() is called internally).
*
* @param interrupt The IRQ number.
*/
void DisableDeepSleepIRQ(IRQn_Type interrupt);
#endif /* FSL_FEATURE_SOC_SYSCON_COUNT */
#if defined(__cplusplus)
}
#endif
/*! @} */
#endif /* _FSL_COMMON_H_ */

View File

@@ -0,0 +1,63 @@
/*
* The Clear BSD License
* Copyright 2014-2016 Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted (subject to the limitations in the disclaimer below) provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __FSL_DEVICE_REGISTERS_H__
#define __FSL_DEVICE_REGISTERS_H__
/*
* Include the cpu specific register header files.
*
* The CPU macro should be declared in the project or makefile.
*/
#if (defined(CPU_MK64FN1M0CAJ12) || defined(CPU_MK64FN1M0VDC12) || defined(CPU_MK64FN1M0VLL12) || \
defined(CPU_MK64FN1M0VLQ12) || defined(CPU_MK64FN1M0VMD12) || defined(CPU_MK64FX512VDC12) || \
defined(CPU_MK64FX512VLL12) || defined(CPU_MK64FX512VLQ12) || defined(CPU_MK64FX512VMD12))
#define K64F12_SERIES
/* CMSIS-style register definitions */
#include "MK64F12.h"
/* CPU specific feature definitions */
#include "MK64F12_features.h"
#else
#error "No valid CPU defined!"
#endif
#endif /* __FSL_DEVICE_REGISTERS_H__ */
/*******************************************************************************
* EOF
******************************************************************************/

1368
apps/include/fsl_flash.h Normal file

File diff suppressed because it is too large Load Diff

5875
apps/include/kinetis.h Normal file

File diff suppressed because it is too large Load Diff

403
apps/include/optparse.h Normal file
View File

@@ -0,0 +1,403 @@
/* Optparse --- portable, reentrant, embeddable, getopt-like option parser
*
* This is free and unencumbered software released into the public domain.
*
* To get the implementation, define OPTPARSE_IMPLEMENTATION.
* Optionally define OPTPARSE_API to control the API's visibility
* and/or linkage (static, __attribute__, __declspec).
*
* The POSIX getopt() option parser has three fatal flaws. These flaws
* are solved by Optparse.
*
* 1) Parser state is stored entirely in global variables, some of
* which are static and inaccessible. This means only one thread can
* use getopt(). It also means it's not possible to recursively parse
* nested sub-arguments while in the middle of argument parsing.
* Optparse fixes this by storing all state on a local struct.
*
* 2) The POSIX standard provides no way to properly reset the parser.
* This means for portable code that getopt() is only good for one
* run, over one argv with one option string. It also means subcommand
* options cannot be processed with getopt(). Most implementations
* provide a method to reset the parser, but it's not portable.
* Optparse provides an optparse_arg() function for stepping over
* subcommands and continuing parsing of options with another option
* string. The Optparse struct itself can be passed around to
* subcommand handlers for additional subcommand option parsing. A
* full reset can be achieved by with an additional optparse_init().
*
* 3) Error messages are printed to stderr. This can be disabled with
* opterr, but the messages themselves are still inaccessible.
* Optparse solves this by writing an error message in its errmsg
* field. The downside to Optparse is that this error message will
* always be in English rather than the current locale.
*
* Optparse should be familiar with anyone accustomed to getopt(), and
* it could be a nearly drop-in replacement. The option string is the
* same and the fields have the same names as the getopt() global
* variables (optarg, optind, optopt).
*
* Optparse also supports GNU-style long options with optparse_long().
* The interface is slightly different and simpler than getopt_long().
*
* By default, argv is permuted as it is parsed, moving non-option
* arguments to the end. This can be disabled by setting the `permute`
* field to 0 after initialization.
*/
#ifndef OPTPARSE_H
#define OPTPARSE_H
#ifndef OPTPARSE_API
# define OPTPARSE_API
#endif
struct optparse {
char **argv;
int permute;
int optind;
int optopt;
char *optarg;
char errmsg[64];
int subopt;
};
enum optparse_argtype {
OPTPARSE_NONE,
OPTPARSE_REQUIRED,
OPTPARSE_OPTIONAL
};
struct optparse_long {
const char *longname;
int shortname;
enum optparse_argtype argtype;
};
/**
* Initializes the parser state.
*/
OPTPARSE_API
void optparse_init(struct optparse *options, char **argv);
/**
* Read the next option in the argv array.
* @param optstring a getopt()-formatted option string.
* @return the next option character, -1 for done, or '?' for error
*
* Just like getopt(), a character followed by no colons means no
* argument. One colon means the option has a required argument. Two
* colons means the option takes an optional argument.
*/
OPTPARSE_API
int optparse(struct optparse *options, const char *optstring);
/**
* Handles GNU-style long options in addition to getopt() options.
* This works a lot like GNU's getopt_long(). The last option in
* longopts must be all zeros, marking the end of the array. The
* longindex argument may be NULL.
*/
OPTPARSE_API
int optparse_long(struct optparse *options,
const struct optparse_long *longopts,
int *longindex);
/**
* Used for stepping over non-option arguments.
* @return the next non-option argument, or NULL for no more arguments
*
* Argument parsing can continue with optparse() after using this
* function. That would be used to parse the options for the
* subcommand returned by optparse_arg(). This function allows you to
* ignore the value of optind.
*/
OPTPARSE_API
char *optparse_arg(struct optparse *options);
/* Implementation */
#ifdef OPTPARSE_IMPLEMENTATION
#define OPTPARSE_MSG_INVALID "invalid option"
#define OPTPARSE_MSG_MISSING "option requires an argument"
#define OPTPARSE_MSG_TOOMANY "option takes no arguments"
static int
optparse_error(struct optparse *options, const char *msg, const char *data)
{
unsigned p = 0;
const char *sep = " -- '";
while (*msg)
options->errmsg[p++] = *msg++;
while (*sep)
options->errmsg[p++] = *sep++;
while (p < sizeof(options->errmsg) - 2 && *data)
options->errmsg[p++] = *data++;
options->errmsg[p++] = '\'';
options->errmsg[p++] = '\0';
return '?';
}
OPTPARSE_API
void
optparse_init(struct optparse *options, char **argv)
{
options->argv = argv;
options->permute = 1;
options->optind = 1;
options->subopt = 0;
options->optarg = 0;
options->errmsg[0] = '\0';
}
static int
optparse_is_dashdash(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
}
static int
optparse_is_shortopt(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
}
static int
optparse_is_longopt(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
}
static void
optparse_permute(struct optparse *options, int index)
{
char *nonoption = options->argv[index];
int i;
for (i = index; i < options->optind - 1; i++)
options->argv[i] = options->argv[i + 1];
options->argv[options->optind - 1] = nonoption;
}
static int
optparse_argtype(const char *optstring, char c)
{
int count = OPTPARSE_NONE;
if (c == ':')
return -1;
for (; *optstring && c != *optstring; optstring++);
if (!*optstring)
return -1;
if (optstring[1] == ':')
count += optstring[2] == ':' ? 2 : 1;
return count;
}
OPTPARSE_API
int
optparse(struct optparse *options, const char *optstring)
{
int type;
char *next;
char *option = options->argv[options->optind];
options->errmsg[0] = '\0';
options->optopt = 0;
options->optarg = 0;
if (option == 0) {
return -1;
} else if (optparse_is_dashdash(option)) {
options->optind++; /* consume "--" */
return -1;
} else if (!optparse_is_shortopt(option)) {
if (options->permute) {
int index = options->optind++;
int r = optparse(options, optstring);
optparse_permute(options, index);
options->optind--;
return r;
} else {
return -1;
}
}
option += options->subopt + 1;
options->optopt = option[0];
type = optparse_argtype(optstring, option[0]);
next = options->argv[options->optind + 1];
switch (type) {
case -1: {
char str[2] = {0, 0};
str[0] = option[0];
options->optind++;
return optparse_error(options, OPTPARSE_MSG_INVALID, str);
}
case OPTPARSE_NONE:
if (option[1]) {
options->subopt++;
} else {
options->subopt = 0;
options->optind++;
}
return option[0];
case OPTPARSE_REQUIRED:
options->subopt = 0;
options->optind++;
if (option[1]) {
options->optarg = option + 1;
} else if (next != 0) {
options->optarg = next;
options->optind++;
} else {
char str[2] = {0, 0};
str[0] = option[0];
options->optarg = 0;
return optparse_error(options, OPTPARSE_MSG_MISSING, str);
}
return option[0];
case OPTPARSE_OPTIONAL:
options->subopt = 0;
options->optind++;
if (option[1])
options->optarg = option + 1;
else
options->optarg = 0;
return option[0];
}
return 0;
}
OPTPARSE_API
char *
optparse_arg(struct optparse *options)
{
char *option = options->argv[options->optind];
options->subopt = 0;
if (option != 0)
options->optind++;
return option;
}
static int
optparse_longopts_end(const struct optparse_long *longopts, int i)
{
return !longopts[i].longname && !longopts[i].shortname;
}
static void
optparse_from_long(const struct optparse_long *longopts, char *optstring)
{
char *p = optstring;
int i;
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
if (longopts[i].shortname && longopts[i].shortname < 127) {
int a;
*p++ = longopts[i].shortname;
for (a = 0; a < (int)longopts[i].argtype; a++)
*p++ = ':';
}
}
*p = '\0';
}
/* Unlike strcmp(), handles options containing "=". */
static int
optparse_longopts_match(const char *longname, const char *option)
{
const char *a = option, *n = longname;
if (longname == 0)
return 0;
for (; *a && *n && *a != '='; a++, n++)
if (*a != *n)
return 0;
return *n == '\0' && (*a == '\0' || *a == '=');
}
/* Return the part after "=", or NULL. */
static char *
optparse_longopts_arg(char *option)
{
for (; *option && *option != '='; option++);
if (*option == '=')
return option + 1;
else
return 0;
}
static int
optparse_long_fallback(struct optparse *options,
const struct optparse_long *longopts,
int *longindex)
{
int result;
char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
optparse_from_long(longopts, optstring);
result = optparse(options, optstring);
if (longindex != 0) {
*longindex = -1;
if (result != -1) {
int i;
for (i = 0; !optparse_longopts_end(longopts, i); i++)
if (longopts[i].shortname == options->optopt)
*longindex = i;
}
}
return result;
}
OPTPARSE_API
int
optparse_long(struct optparse *options,
const struct optparse_long *longopts,
int *longindex)
{
int i;
char *option = options->argv[options->optind];
if (option == 0) {
return -1;
} else if (optparse_is_dashdash(option)) {
options->optind++; /* consume "--" */
return -1;
} else if (optparse_is_shortopt(option)) {
return optparse_long_fallback(options, longopts, longindex);
} else if (!optparse_is_longopt(option)) {
if (options->permute) {
int index = options->optind++;
int r = optparse_long(options, longopts, longindex);
optparse_permute(options, index);
options->optind--;
return r;
} else {
return -1;
}
}
/* Parse as long option. */
options->errmsg[0] = '\0';
options->optopt = 0;
options->optarg = 0;
option += 2; /* skip "--" */
options->optind++;
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
const char *name = longopts[i].longname;
if (optparse_longopts_match(name, option)) {
char *arg;
if (longindex)
*longindex = i;
options->optopt = longopts[i].shortname;
arg = optparse_longopts_arg(option);
if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
return optparse_error(options, OPTPARSE_MSG_TOOMANY, name);
} if (arg != 0) {
options->optarg = arg;
} else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
options->optarg = options->argv[options->optind];
if (options->optarg == 0)
return optparse_error(options, OPTPARSE_MSG_MISSING, name);
else
options->optind++;
}
return options->optopt;
}
}
return optparse_error(options, OPTPARSE_MSG_INVALID, option);
}
#endif /* OPTPARSE_IMPLEMENTATION */
#endif /* OPTPARSE_H */

View File

@@ -0,0 +1,174 @@
/*
** ###################################################################
** Processors: MK64FN1M0CAJ12
** MK64FN1M0VDC12
** MK64FN1M0VLL12
** MK64FN1M0VLQ12
** MK64FN1M0VMD12
** MK64FX512VDC12
** MK64FX512VLL12
** MK64FX512VLQ12
** MK64FX512VMD12
**
** Compilers: Keil ARM C/C++ Compiler
** Freescale C/C++ for Embedded ARM
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** MCUXpresso Compiler
**
** Reference manual: K64P144M120SF5RM, Rev.2, January 2014
** Version: rev. 2.9, 2016-03-21
** Build: b170112
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright (c) 2016 Freescale Semiconductor, Inc.
** Copyright 2016 - 2017 NXP
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
**
** o Redistributions of source code must retain the above copyright notice, this list
** of conditions and the following disclaimer.
**
** o Redistributions in binary form must reproduce the above copyright notice, this
** list of conditions and the following disclaimer in the documentation and/or
** other materials provided with the distribution.
**
** o Neither the name of the copyright holder nor the names of its
** contributors may be used to endorse or promote products derived from this
** software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2013-08-12)
** Initial version.
** - rev. 2.0 (2013-10-29)
** Register accessor macros added to the memory map.
** Symbols for Processor Expert memory map compatibility added to the memory map.
** Startup file for gcc has been updated according to CMSIS 3.2.
** System initialization updated.
** MCG - registers updated.
** PORTA, PORTB, PORTC, PORTE - registers for digital filter removed.
** - rev. 2.1 (2013-10-30)
** Definition of BITBAND macros updated to support peripherals with 32-bit acces disabled.
** - rev. 2.2 (2013-12-09)
** DMA - EARS register removed.
** AIPS0, AIPS1 - MPRA register updated.
** - rev. 2.3 (2014-01-24)
** Update according to reference manual rev. 2
** ENET, MCG, MCM, SIM, USB - registers updated
** - rev. 2.4 (2014-02-10)
** The declaration of clock configurations has been moved to separate header file system_MK64F12.h
** Update of SystemInit() and SystemCoreClockUpdate() functions.
** - rev. 2.5 (2014-02-10)
** The declaration of clock configurations has been moved to separate header file system_MK64F12.h
** Update of SystemInit() and SystemCoreClockUpdate() functions.
** Module access macro module_BASES replaced by module_BASE_PTRS.
** - rev. 2.6 (2014-08-28)
** Update of system files - default clock configuration changed.
** Update of startup files - possibility to override DefaultISR added.
** - rev. 2.7 (2014-10-14)
** Interrupt INT_LPTimer renamed to INT_LPTMR0, interrupt INT_Watchdog renamed to INT_WDOG_EWM.
** - rev. 2.8 (2015-02-19)
** Renamed interrupt vector LLW to LLWU.
** - rev. 2.9 (2016-03-21)
** Added MK64FN1M0CAJ12 part.
** GPIO - renamed port instances: PTx -> GPIOx.
**
** ###################################################################
*/
/*!
* @file MK64F12
* @version 2.9
* @date 2016-03-21
* @brief Device specific configuration file for MK64F12 (header file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#ifndef _SYSTEM_MK64F12_H_
#define _SYSTEM_MK64F12_H_ /**< Symbol preventing repeated inclusion */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#ifndef DISABLE_WDOG
#define DISABLE_WDOG 1
#endif
/* Define clock source values */
#define CPU_XTAL_CLK_HZ 50000000u /* Value of the external crystal or oscillator clock frequency in Hz */
#define CPU_XTAL32k_CLK_HZ 32768u /* Value of the external 32k crystal or oscillator clock frequency in Hz */
#define CPU_INT_SLOW_CLK_HZ 32768u /* Value of the slow internal oscillator clock frequency in Hz */
#define CPU_INT_FAST_CLK_HZ 4000000u /* Value of the fast internal oscillator clock frequency in Hz */
#define CPU_INT_IRC_CLK_HZ 48000000u /* Value of the 48M internal oscillator clock frequency in Hz */
/* RTC oscillator setting */
/* RTC_CR: SC2P=0,SC4P=0,SC8P=0,SC16P=0,CLKO=1,OSCE=1,WPS=0,UM=0,SUP=0,WPE=0,SWR=0 */
#define SYSTEM_RTC_CR_VALUE 0x0300U /* RTC_CR */
/* Low power mode enable */
/* SMC_PMPROT: AVLP=1,ALLS=1,AVLLS=1 */
#define SYSTEM_SMC_PMPROT_VALUE 0x2AU /* SMC_PMPROT */
#define DEFAULT_SYSTEM_CLOCK 20971520u /* Default System clock value */
/**
* @brief System clock frequency (core clock)
*
* The system clock frequency supplied to the SysTick timer and the processor
* core clock. This variable can be used by the user application to setup the
* SysTick timer or configure other parameters. It may also be used by debugger to
* query the frequency of the debug timer or configure the trace clock speed
* SystemCoreClock is initialized with a correct predefined value.
*/
extern uint32_t SystemCoreClock;
/**
* @brief Setup the microcontroller system.
*
* Typically this function configures the oscillator (PLL) that is part of the
* microcontroller device. For systems with variable clock speed it also updates
* the variable SystemCoreClock. SystemInit is called from startup_device file.
*/
void SystemInit (void);
/**
* @brief Updates the SystemCoreClock variable.
*
* It must be called whenever the core clock is changed during program
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
* the current core clock.
*/
void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* _SYSTEM_MK64F12_H_ */

833
apps/include/tranzputer_m.h Executable file
View File

@@ -0,0 +1,833 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: tranzputer.h
// Created: May 2020
// Author(s): Philip Smart
// Description: The TranZPUter library.
// This file contains methods which allow applications to access and control the traZPUter board and the underlying Sharp MZ80A host.
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// Jul 2020 - Updates to accommodate v2.1 of the tranZPUter board.
// Sep 2020 - Updates to accommodate v2.2 of the tranZPUter board.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef TRANZPUTER_H
#define TRANZPUTER_H
#ifdef __cplusplus
extern "C" {
#endif
// Configurable constants.
//
#define REFRESH_BYTE_COUNT 8 // This constant controls the number of bytes read/written to the z80 bus before a refresh cycle is needed.
#define RFSH_BYTE_CNT 256 // Number of bytes we can write before needing a full refresh for the DRAM.
#define HOST_MON_TEST_VECTOR 0x4 // Address in the host monitor to test to identify host type.
#define DEFAULT_BUSREQ_TIMEOUT 5000 // Timeout for a Z80 Bus request operation in milliseconds.
#define DEFAULT_RESET_PULSE_WIDTH 500000 // Pulse width of a reset signal in K64F clock ticks.
// tranZPUter Memory Modes - select one of the 32 possible memory models using these constants.
//
#define TZMM_ORIG 0x00 // Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
#define TZMM_BOOT 0x01 // Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
#define TZMM_TZFS 0x02 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
#define TZMM_TZFS2 0x03 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
#define TZMM_TZFS3 0x04 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
#define TZMM_TZFS4 0x05 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
#define TZMM_CPM 0x06 // CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
#define TZMM_CPM2 0x07 // CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
// Special case for 0000:003F (interrupt vectors) which resides in block 4, F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
#define TZMM_MZ700_0 0x0a // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
#define TZMM_MZ700_1 0x0b // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
#define TZMM_MZ700_2 0x0c // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
#define TZMM_MZ700_3 0x0d // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
#define TZMM_MZ700_4 0x0e // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
#define TZMM_FPGA 0x15 // Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
#define TZMM_TZPUM 0x16 // Everything is on mainboard, no access to tranZPUter memory.
#define TZMM_TZPU 0x17 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory. K64F drives A18-A16 allowing full access to RAM.
#define TZMM_TZPU0 0x18 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
#define TZMM_TZPU1 0x19 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
#define TZMM_TZPU2 0x1A // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
#define TZMM_TZPU3 0x1B // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
#define TZMM_TZPU4 0x1C // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
#define TZMM_TZPU5 0x1D // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
#define TZMM_TZPU6 0x1E // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
#define TZMM_TZPU7 0x1F // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
#define TZMM_ENIOWAIT 0x20 // Enable wait state generator for Sharp system IO operations in region 0xE0-0xFF.
// IO addresses on the tranZPUter or mainboard.
//
#define IO_TZ_CTRLLATCH 0x60 // Control latch which specifies the Memory Model/mode.
#define IO_TZ_SETXMHZ 0x62 // Switch to alternate CPU frequency provided by K64F.
#define IO_TZ_SET2MHZ 0x64 // Switch to system CPU frequency.
#define IO_TZ_CLKSELRD 0x66 // Read the status of the clock select, ie. which clock is connected to the CPU.
#define IO_TZ_SVCREQ 0x68 // Service request from the Z80 to be provided by the K64F.
#define IO_TZ_SYSREQ 0x6A // System request from the Z80 to be provided by the K64F.
#define IO_TZ_CPUCFG 0x6C // Version 2.2 CPU configuration register.
#define IO_TZ_CPUSTATUS 0x6C // Version 2.2 CPU runtime status register.
#define IO_TZ_CPUINFO 0x6D // Version 2.2 CPU information register.
#define IO_TZ_CPLDCFG 0x6E // Version 2.1 CPLD configuration register.
#define IO_TZ_CPLDSTATUS 0x6E // Version 2.1 CPLD status register.
#define IO_TZ_CPLDINFO 0x6F // Version 2.1 CPLD version information register.
#define IO_TZ_SYSCTRL 0xF0 // System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
#define IO_TZ_GRAMMODE 0xF4 // MZ80B Graphics mode. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display.
#define IO_TZ_VMCTRL 0xF8 // Video Module control register. [2:0] - 000 (default) = MZ80A, 001 = MZ-700, 010 = MZ800, 011 = MZ80B, 100 = MZ80K, 101 = MZ80C, 110 = MZ1200, 111 = MZ2000. [3] = 0 - 40 col, 1 - 80 col.
#define IO_TZ_VMGRMODE 0xF9 // Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
#define IO_TZ_VMREDMASK 0xFA // Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMGREENMASK 0xFB // Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMBLUEMASK 0xFC // Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMPAGE 0xFD // Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
// IO register constants.
//
#define CPUMODE_SET_Z80 0x00 // Set the CPU to the hard Z80.
#define CPUMODE_SET_T80 0x01 // Set the CPU to the soft T80.
#define CPUMODE_SET_ZPU_EVO 0x02 // Set the CPU to the soft ZPU Evolution.
#define CPUMODE_SET_AAA 0x04 // Place holder for a future soft CPU.
#define CPUMODE_SET_BBB 0x08 // Place holder for a future soft CPU.
#define CPUMODE_SET_CCC 0x10 // Place holder for a future soft CPU.
#define CPUMODE_SET_DDD 0x20 // Place holder for a future soft CPU.
#define CPUMODE_IS_Z80 0x00 // Status value to indicate if the hard Z80 available.
#define CPUMODE_IS_T80 0x01 // Status value to indicate if the soft T80 available.
#define CPUMODE_IS_ZPU_EVO 0x02 // Status value to indicate if the soft ZPU Evolution available.
#define CPUMODE_IS_AAA 0x04 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_IS_BBB 0x08 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_IS_CCC 0x10 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_IS_DDD 0x20 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_CLK_EN 0x40 // Toggle the soft CPU clock, 1 = enable, 0 = disable.
#define CPUMODE_RESET_CPU 0x80 // Reset the soft CPU. Active high, when high the CPU is held in RESET, when low the CPU runs.
#define CPUMODE_IS_SOFT_AVAIL 0x040 // Marker to indicate if the underlying FPGA can support soft CPU's.
#define CPUMODE_IS_SOFT_MASK 0x03F // Mask to filter out the Soft CPU availability flags.
// Video Module control bits.
#define SYSMODE_MZ80A 0x00 // System board mode MZ80A, 2MHz CPU/Bus.
#define SYSMODE_MZ80B 0x01 // System board mode MZ80B, 4MHz CPU/Bus.
#define SYSMODE_MZ700 0x02 // System board mode MZ700, 3.54MHz CPU/Bus.
#define VMMODE_MASK 0xF8 // Mask to mask out video mode.
#define VMMODE_MZ80K 0x00 // Video mode = MZ80K
#define VMMODE_MZ80C 0x01 // Video mode = MZ80C
#define VMMODE_MZ1200 0x02 // Video mode = MZ1200
#define VMMODE_MZ80A 0x03 // Video mode = MZ80A
#define VMMODE_MZ700 0x04 // Video mode = MZ700
#define VMMODE_MZ800 0x05 // Video mode = MZ800
#define VMMODE_MZ80B 0x06 // Video mode = MZ80B
#define VMMODE_MZ2000 0x07 // Video mode = MZ2000
#define VMMODE_80CHAR 0x08 // Enable 80 character display.
#define VMMODE_80CHAR_MASK 0xF7 // Mask to filter out display width control bit.
#define VMMODE_COLOUR 0x10 // Enable colour display.
#define VMMODE_COLOUR_MASK 0xEF // Mask to filter out colour control bit.
#define VMMODE_PCGRAM 0x20 // Enable PCG RAM.
#define VMMODE_VGA_MASK 0x3F // Mask to filter out the VGA mode bits.
#define VMMODE_VGA_OFF 0x00 // Set VGA mode off, external monitor is driven by standard internal signals.
#define VMMODE_VGA_640x480 0x40 // Set external monitor to VGA 640x480 @ 60Hz mode.
#define VMMODE_VGA_1024x768 0x80 // Set external monitor to VGA 1024x768 @ 60Hz mode.
#define VMMODE_VGA_800x600 0xC0 // Set external monitor to VGA 800x600 @ 60Hz mode.
// VGA mode border control constants.
//
#define VMBORDER_BLACK 0x00 // VGA has a black border.
#define VMBORDER_BLUE 0x01 // VGA has a blue border.
#define VMBORDER_RED 0x02 // VGA has a red border.
#define VMBORDER_PURPLE 0x03 // VGA has a purple border.
#define VMBORDER_GREEN 0x04 // VGA has a green border.
#define VMBORDER_CYAN 0x05 // VGA has a cyan border.
#define VMBORDER_YELLOW 0x06 // VGA has a yellow border.
#define VMBORDER_WHITE 0x07 // VGA has a white border.
#define VMBORDER_MASK 0xF8 // Mask to filter out current border setting.
// Sharp MZ colour attributes.
#define VMATTR_FG_BLACK 0x00 // Foreground black character attribute.
#define VMATTR_FG_BLUE 0x10 // Foreground blue character attribute.
#define VMATTR_FG_RED 0x20 // Foreground red character attribute.
#define VMATTR_FG_PURPLE 0x30 // Foreground purple character attribute.
#define VMATTR_FG_GREEN 0x40 // Foreground green character attribute.
#define VMATTR_FG_CYAN 0x50 // Foreground cyan character attribute.
#define VMATTR_FG_YELLOW 0x60 // Foreground yellow character attribute.
#define VMATTR_FG_WHITE 0x70 // Foreground white character attribute.
#define VMATTR_FG_MASKOUT 0x8F // Mask to filter out foreground attribute.
#define VMATTR_FG_MASKIN 0x70 // Mask to filter out foreground attribute.
#define VMATTR_BG_BLACK 0x00 // Background black character attribute.
#define VMATTR_BG_BLUE 0x01 // Background blue character attribute.
#define VMATTR_BG_RED 0x02 // Background red character attribute.
#define VMATTR_BG_PURPLE 0x03 // Background purple character attribute.
#define VMATTR_BG_GREEN 0x04 // Background green character attribute.
#define VMATTR_BG_CYAN 0x05 // Background cyan character attribute.
#define VMATTR_BG_YELLOW 0x06 // Background yellow character attribute.
#define VMATTR_BG_WHITE 0x07 // Background white character attribute.
#define VMATTR_BG_MASKOUT 0xF8 // Mask to filter out background attribute.
#define VMATTR_BG_MASKIN 0x07 // Mask to filter out background attribute.
// Sharp MZ constants.
//
#define MZ_MROM_ADDR 0x0000 // Monitor ROM start address.
#define MZ_MROM_STACK_ADDR 0x1000 // Monitor ROM start stack address.
#define MZ_MROM_STACK_SIZE 0x0200 // Monitor ROM stack size.
#define MZ_UROM_ADDR 0xE800 // User ROM start address.
#define MZ_BANKRAM_ADDR 0xF000 // Floppy API address which is used in TZFS as the paged RAM for additional functionality.
#define MZ_ZOS_ADDR 0x100000 // zOS boot location for the ZPU in FPGA BRAM memory.
#define MZ_CMT_ADDR 0x10F0 // Address of the CMT (tape) header record.
#define MZ_CMT_DEFAULT_LOAD_ADDR 0x1200 // The default load address for a CMT, anything below this is normally illegal.
#define MZ_VID_RAM_ADDR 0xD000 // Start of Video RAM
#define MZ_VID_RAM_SIZE 2048 // Size of Video RAM.
#define MZ_VID_DFLT_BYTE 0x00 // Default character (SPACE) for video RAM.
#define MZ_ATTR_RAM_ADDR 0xD800 // On machines with the upgrade, the start of the Attribute RAM.
#define MZ_ATTR_RAM_SIZE 2048 // Size of the attribute RAM.
#define MZ_ATTR_DFLT_BYTE 0x07 // Default colour (White on Black) for the attribute.
#define MZ_SCROL_BASE 0xE200 // Base address of the hardware scroll registers.
#define MZ_SCROL_END 0xE2FF // End address of the hardware scroll registers.
#define MZ_MEMORY_SWAP 0xE00C // Address when read swaps the memory from 0000-0FFF -> C000-CFFF
#define MZ_MEMORY_RESET 0xE010 // Address when read resets the memory to the default location 0000-0FFF.
#define MZ_CRT_NORMAL 0xE014 // Address when read sets the CRT to normal display mode.
#define MZ_CRT_INVERSE 0xE018 // Address when read sets the CRT to inverted display mode.
#define MZ_80A_CPU_FREQ 2000000 // CPU Speed of the Sharp MZ-80A
#define MZ_700_CPU_FREQ 3580000 // CPU Speed of the Sharp MZ-700
#define MZ_80B_CPU_FREQ 4000000 // CPU Speed of the Sharp MZ-80B
#define MZ_ROM_SA1510_40C "0:\\TZFS\\SA1510.ROM" // Original 40 character Monitor ROM.
#define MZ_ROM_SA1510_80C "0:\\TZFS\\SA1510-8.ROM" // Original Monitor ROM patched for 80 character screen mode.
#define MZ_ROM_1Z_013A_40C "0:\\TZFS\\1Z-013A.ROM" // Original 40 character Monitor ROM for the Sharp MZ700.
#define MZ_ROM_1Z_013A_80C "0:\\TZFS\\1Z-013A-8.ROM" // Original Monitor ROM patched for the Sharp MZ700 patched for 80 column mode.
#define MZ_ROM_1Z_013A_KM_40C "0:\\TZFS\\1Z-013A-KM.ROM" // Original 40 character Monitor ROM for the Sharp MZ700 with keyboard remapped for the MZ80A.
#define MZ_ROM_1Z_013A_KM_80C "0:\\TZFS\\1Z-013A-KM-8.ROM" // Original Monitor ROM patched for the Sharp MZ700 with keyboard remapped for the MZ80A and patched for 80 column mode.
#define MZ_ROM_MZ80B_IPL "0:\\TZFS\\MZ80B_IPL.ROM" // Original IPL ROM for the Sharp MZ-80B.
#define MZ_ROM_TZFS "0:\\TZFS\\TZFS.ROM" // tranZPUter Filing System ROM.
#define MZ_ROM_ZPU_ZOS "0:\\ZOS\\ZOS.ROM" // zOS for the ZPU running on the tranZPUter SW-700 board.
// CP/M constants.
//
#define CPM_MAX_DRIVES 16 // Maximum number of drives in CP/M.
#define CPM_FILE_CCPBDOS "0:\\CPM\\CPM22.BIN" // CP/M CCP and BDOS for warm start reloads.
#define CPM_DRIVE_TMPL "0:\\CPM\\CPMDSK%02u.RAW" // Template for CPM disk drives stored on the SD card.
#define CPM_SECTORS_PER_TRACK 32 // Number of sectors in a track on the virtual CPM disk.
#define CPM_TRACKS_PER_DISK 1024 // Number of tracks on a disk.
// Service request constants.
//
#define TZSVC_CMD_STRUCT_ADDR_TZFS 0x0ED80 // Address of the command structure within TZFS - exists in 64K Block 0.
#define TZSVC_CMD_STRUCT_ADDR_CPM 0x4F560 // Address of the command structure within CP/M - exists in 64K Block 4.
#define TZSVC_CMD_STRUCT_ADDR_MZ700 0x6FD80 // Address of the command structure within MZ700 compatible programs - exists in 64K Block 6.
#define TZSVC_CMD_STRUCT_ADDR_ZOS 0x11FD80 // 0x7FD80 // Address of the command structure for zOS use, exists in shared memory rather than FPGA. Spans top of block 6 and all of block 7.
#define TZSVC_CMD_STRUCT_SIZE 0x280 // Size of the inter z80/K64 service command memory.
#define TZSVC_CMD_SIZE (sizeof(t_svcControl)-TZSVC_SECTOR_SIZE)
#define TZVC_MAX_CMPCT_DIRENT_BLOCK TZSVC_SECTOR_SIZE/TZSVC_CMPHDR_SIZE // Maximum number of directory entries per sector.
#define TZSVC_MAX_DIR_ENTRIES 255 // Maximum number of files in one directory, any more than this will be ignored.
#define TZSVC_CMPHDR_SIZE 32 // Compacted header size, contains everything except the comment field, padded out to 32bytes.
#define MZF_FILLER_LEN 8 // Filler to pad a compacted header entry to a power of 2 length.
#define TZVC_MAX_DIRENT_BLOCK TZSVC_SECTOR_SIZE/MZF_HEADER_SIZE // Maximum number of directory entries per sector.
#define TZSVC_CMD_READDIR 0x01 // Service command to open a directory and return the first block of entries.
#define TZSVC_CMD_NEXTDIR 0x02 // Service command to return the next block of an open directory.
#define TZSVC_CMD_READFILE 0x03 // Service command to open a file and return the first block.
#define TZSVC_CMD_NEXTREADFILE 0x04 // Service command to return the next block of an open file.
#define TZSVC_CMD_WRITEFILE 0x05 // Service command to create a file and save the first block.
#define TZSVC_CMD_NEXTWRITEFILE 0x06 // Service command to write the next block to the open file.
#define TZSVC_CMD_CLOSE 0x07 // Service command to close any open file or directory.
#define TZSVC_CMD_LOADFILE 0x08 // Service command to load a file directly into tranZPUter memory.
#define TZSVC_CMD_SAVEFILE 0x09 // Service command to save a file directly from tranZPUter memory.
#define TZSVC_CMD_ERASEFILE 0x0a // Service command to erase a file on the SD card.
#define TZSVC_CMD_CHANGEDIR 0x0b // Service command to change active directory on the SD card.
#define TZSVC_CMD_LOAD40ABIOS 0x20 // Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD80ABIOS 0x21 // Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD700BIOS40 0x22 // Service command requesting that the MZ700 1Z-013A 40 column BIOS is loaded.
#define TZSVC_CMD_LOAD700BIOS80 0x23 // Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
#define TZSVC_CMD_LOAD80BIPL 0x24 // Service command requesting the MZ-80B IPL is loaded.
#define TZSVC_CMD_LOADBDOS 0x30 // Service command to reload CPM BDOS+CCP.
#define TZSVC_CMD_ADDSDDRIVE 0x31 // Service command to attach a CPM disk to a drive number.
#define TZSVC_CMD_READSDDRIVE 0x32 // Service command to read an attached SD file as a CPM disk drive.
#define TZSVC_CMD_WRITESDDRIVE 0x33 // Service command to write to a CPM disk drive which is an attached SD file.
#define TZSVC_CMD_CPU_BASEFREQ 0x40 // Service command to switch to the mainboard frequency.
#define TZSVC_CMD_CPU_ALTFREQ 0x41 // Service command to switch to the alternate frequency provided by the K64F.
#define TZSVC_CMD_CPU_CHGFREQ 0x42 // Service command to set the alternate frequency in hertz.
#define TZSVC_CMD_CPU_SETZ80 0x50 // Service command to switch to the external Z80 hard cpu.
#define TZSVC_CMD_CPU_SETT80 0x51 // Service command to switch to the internal T80 soft cpu.
#define TZSVC_CMD_CPU_SETZPUEVO 0x52 // Service command to switch to the internal ZPU Evolution cpu.
#define TZSVC_CMD_SD_DISKINIT 0x60 // Service command to initialise and provide raw access to the underlying SD card.
#define TZSVC_CMD_SD_READSECTOR 0x61 // Service command to provide raw read access to the underlying SD card.
#define TZSVC_CMD_SD_WRITESECTOR 0x62 // Service command to provide raw write access to the underlying SD card.
#define TZSVC_CMD_EXIT 0x7F // Service command to terminate TZFS and restart the machine in original mode.
#define TZSVC_DEFAULT_MZF_DIR "MZF" // Default directory where MZF files are stored.
#define TZSVC_DEFAULT_CAS_DIR "CAS" // Default directory where BASIC CASsette files are stored.
#define TZSVC_DEFAULT_BAS_DIR "BAS" // Default directory where BASIC text files are stored.
#define TZSVC_DEFAULT_MZF_EXT "MZF" // Default file extension for MZF files.
#define TZSVC_DEFAULT_CAS_EXT "CAS" // Default file extension for CASsette files.
#define TZSVC_DEFAULT_BAS_EXT "BAS" // Default file extension for BASic script files stored in readable text.
#define TZSVC_DEFAULT_WILDCARD "*" // Default wildcard file matching.
#define TZSVC_RESULT_OFFSET 0x01 // Offset into structure of the result byte.
#define TZSVC_DIRNAME_SIZE 20 // Limit is size of FAT32 directory name.
#define TZSVC_WILDCARD_SIZE 20 // Very basic pattern matching so small size.
#define TZSVC_FILENAME_SIZE MZF_FILENAME_LEN // Length of a Sharp MZF filename.
#define TZSVC_LONG_FNAME_SIZE (sizeof(t_svcCmpDirEnt) - 1) // Length of a standard filename to fit inside a directory entry.
#define TZSVC_LONG_FMT_FNAME_SIZE 20 // Length of a standard filename formatted in a directory listing.
#define TZSVC_SECTOR_SIZE 512 // SD Card sector buffer size.
#define TZSVC_STATUS_OK 0x00 // Flag to indicate the K64F processing completed successfully.
#define TZSVC_STATUS_FILE_ERROR 0x01 // Flag to indicate a file or directory error.
#define TZSVC_STATUS_BAD_CMD 0x02 // Flag to indicate a bad service command was requested.
#define TZSVC_STATUS_BAD_REQ 0x03 // Flag to indicate a bad request was made, the service status request flag was not set.
#define TZSVC_STATUS_REQUEST 0xFE // Flag to indicate Z80 has posted a request.
#define TZSVC_STATUS_PROCESSING 0xFF // Flag to indicate the K64F is processing a command.
#define TZSVC_OPEN 0x00 // Service request to open a directory or file.
#define TZSVC_NEXT 0x01 // Service request to return the next directory block or file block or write the next file block.
#define TZSVC_CLOSE 0x02 // Service request to close open dir/file.
// Constants for the Sharp MZ80A MZF file format.
#define MZF_HEADER_SIZE 128 // Size of the MZF header.
#define MZF_ATTRIBUTE 0x00 // Code Type, 01 = Machine Code.
#define MZF_FILENAME 0x01 // Title/Name (17 bytes).
#define MZF_FILENAME_LEN 17 // Length of the filename, it is not NULL terminated, generally a CR can be taken as terminator but not guaranteed.
#define MZF_FILESIZE 0x12 // Size of program.
#define MZF_LOADADDR 0x14 // Load address of program.
#define MZF_EXECADDR 0x16 // Exec address of program.
#define MZF_COMMENT 0x18 // Comment, used for details of the file or startup code.
#define MZF_COMMENT_LEN 104 // Length of the comment field.
// Constants for other handled file formats.
//
#define CAS_HEADER_SIZE 256 // Size of the CASsette header.
// Pin Constants - Pins assigned at the hardware level to specific tasks/signals.
//
#define MAX_TRANZPUTER_PINS 51
#define Z80_WR_PIN 20 // 48
#define Z80_RD_PIN 5 // 55
#define Z80_IORQ_PIN 8
#define Z80_MREQ_PIN 7
#define Z80_A0_PIN 15
#define Z80_A1_PIN 22
#define Z80_A2_PIN 23
#define Z80_A3_PIN 9
#define Z80_A4_PIN 10
#define Z80_A5_PIN 13
#define Z80_A6_PIN 11
#define Z80_A7_PIN 12
#define Z80_A8_PIN 35
#define Z80_A9_PIN 36
#define Z80_A10_PIN 37
#define Z80_A11_PIN 38
#define Z80_A12_PIN 64 // 3
#define Z80_A13_PIN 65 // 4
#define Z80_A14_PIN 66 // 26
#define Z80_A15_PIN 67 // 27
#define Z80_A16_PIN 68 // 33
#define Z80_A17_PIN 69 // 34
#define Z80_A18_PIN 70 // 24
#define Z80_A19_PIN 16
#define Z80_A20_PIN 17
#define Z80_A21_PIN 19
#define Z80_A22_PIN 18
#define Z80_A23_PIN 71 // 49
#define Z80_D0_PIN 0
#define Z80_D1_PIN 1
#define Z80_D2_PIN 29
#define Z80_D3_PIN 30
#define Z80_D4_PIN 43
#define Z80_D5_PIN 46
#define Z80_D6_PIN 44
#define Z80_D7_PIN 45
#define Z80_WAIT_PIN 31 // 54
#define Z80_BUSACK_PIN 24 // 5
#define Z80_NMI_PIN 39
#define Z80_INT_PIN 28
#define Z80_RESET_PIN 6
#define SYSCLK_PIN 25
#define CTL_RFSH_PIN 4 // 53
#define CTL_HALT_PIN 26 // 51
#define CTL_M1_PIN 3 // 20
#define CTL_WAIT_PIN 27
#define CTL_BUSRQ_PIN 2
#define CTL_MBSEL_PIN 21
#define CTL_CLK_PIN 14
#define CTL_BUSACK_PIN 32 // 47
#define CTL_SVCREQ_PIN 33 // 56
// IRQ mask values for the different types of IRQ trigger.
//
#define IRQ_MASK_CHANGE 0x10B0000
#define IRQ_MASK_RISING 0x1090000 //0x040040
#define IRQ_MASK_FALLING 0x10A0000
#define IRQ_MASK_LOW 0x1080000
#define IRQ_MASK_HIGH 0x10C0000
// Customised pin manipulation methods implemented as stripped down macros. The original had too much additional overhead with procedure call and validation tests,
// speed is of the essence for this project as pins change mode and value constantly.
//
#define STR(x) #x
#define XSTR(s) STR(s)
#define pinLow(a) *portClearRegister(pinMap[a]) = 1
#define pinHigh(a) *portSetRegister(pinMap[a]) = 1
#define pinSet(a, b) if(b) { *portSetRegister(pinMap[a]) = 1; } else { *portClearRegister(pinMap[a]) = 1; }
#define pinGet(a) *portInputRegister(pinMap[a])
#define pinInput(a) { *portModeRegister(pinMap[a]) = 0; *ioPin[a] = PORT_PCR_MUX(1) | PORT_PCR_PFE | PORT_PCR_PE | PORT_PCR_PS; }
#define pinOutput(a) { *portModeRegister(pinMap[a]) = 1;\
*ioPin[a] = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);\
*ioPin[a] &= ~PORT_PCR_ODE; }
#define pinOutputSet(a,b) { if(b) { *portSetRegister(pinMap[a]) = 1; } else { *portClearRegister(pinMap[a]) = 1; }\
*portModeRegister(pinMap[a]) = 1;\
*ioPin[a] = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);\
*ioPin[a] &= ~PORT_PCR_ODE; }
#define installIRQ(a, mask) { uint32_t cfg;\
cfg = *ioPin[a];\
cfg &= ~0x000F0000;\
*ioPin[a] = cfg;\
cfg |= mask;\
*ioPin[a] = cfg;\
}
#define removeIRQ(a) { \
*ioPin[a] = ((*ioPin[a] & ~0x000F0000) | 0x01000000);\
}
#define pinIndex(a) getPinIndex(pinMap[a])
#define setZ80Data(a) { GPIOB_PDOR = (GPIOB_PDOR & 0xff00ffff) | ((a << 16) & 0x00ff0000); }
#define setZ80DataAsOutput() { GPIOB_PDDR = (GPIOB_PDDR & 0x0000ffff) | 0x00ff0000; }
#define setZ80DataAsInput() { GPIOB_PDDR = (GPIOB_PDDR & 0x0000ffff); }
#define setZ80Addr(a) { GPIOC_PDOR = (GPIOC_PDOR & 0xfff80000) | (a & 0x0007ffff); GPIOB_PDOR = (GPIOB_PDOR & 0xFFFFFDF0) | (((a >> 14)&0x200) | ((a >> 19)&0xF)); }
#define setZ80AddrAsOutput() { GPIOC_PDDR = 0x0007ffff; GPIOB_PDDR = GPIOB_PDDR | 0x20F; }
#define setZ80AddrAsInput() { GPIOC_PDDR = 0x00000000; GPIOB_PDDR = GPIOB_PDDR & 0xFFFFFDF0; }
#define setZ80AddrLower(a) { GPIOC_PDOR = (GPIOC_PDOR & 0xffffff00) | (a & 0x000000ff); }
#define setZ80RefreshAddr(a) { GPIOC_PDOR = (GPIOC_PDOR & 0xffffff80) | (a & 0x0000007f); }
#define readZ80AddrLower() ( GPIOC_PDIR & 0x000000ff )
#define readZ80Addr() ( (GPIOC_PDIR & 0x0000ffff) )
#define readZ80DataBus() ( (GPIOB_PDIR >> 16) & 0x000000ff )
//#define readCtrlLatch() ( ((GPIOB_PDIR & 0x00000200) >> 5) | (GPIOB_PDIR & 0x0000000f) )
#define readCtrlLatchDirect() ( inZ80IO(IO_TZ_CTRLLATCH) )
#define readCtrlLatch() ( readZ80IO(IO_TZ_CTRLLATCH, TRANZPUTER) )
#define writeCtrlLatch(a) { setZ80Direction(WRITE); outZ80IO(IO_TZ_CTRLLATCH, a); }
//#define setZ80Direction(a) { for(uint8_t idx=Z80_D0; idx <= Z80_D7; idx++) { if(a == WRITE) { pinOutput(idx); } else { pinInput(idx); } }; z80Control.busDir = a; }
#define setZ80Direction(a) {{ if(a == WRITE) { setZ80DataAsOutput(); } else { setZ80DataAsInput(); } }; z80Control.busDir = a; }
#define reqZ80BusChange(a) { if(a == MAINBOARD_ACCESS && z80Control.ctrlMode == TRANZPUTER_ACCESS) \
{\
pinHigh(CTL_MBSEL);\
z80Control.ctrlMode = MAINBOARD_ACCESS;\
z80Control.curCtrlLatch = TZMM_ORIG | TZMM_ENIOWAIT;\
writeCtrlLatch(z80Control.curCtrlLatch);\
} else if(a == TRANZPUTER_ACCESS && z80Control.ctrlMode == MAINBOARD_ACCESS)\
{\
pinLow(CTL_MBSEL);\
z80Control.ctrlMode = TRANZPUTER_ACCESS;\
z80Control.curCtrlLatch = TZMM_TZPU | TZMM_ENIOWAIT;\
writeCtrlLatch(z80Control.curCtrlLatch);\
} }
// Lower level macro without pin mapping as this is called in the ResetHandler to halt the Z80 whilst the K64F starts up and is able to load up tranZPUter software.
#define holdZ80() { \
*portModeRegister(CTL_BUSRQ_PIN) = 1; \
*portConfigRegister(CTL_BUSRQ_PIN) = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \
*portConfigRegister(CTL_BUSRQ_PIN) &= ~PORT_PCR_ODE; \
*portClearRegister(CTL_BUSRQ_PIN) = 1; \
}
// Enumeration of the various pins on the project. These enums make it easy to refer to a signal and they are mapped
// to the actual hardware pin via the pinMap array.
// One of the big advantages is that a swath of pins, such as the address lines, can be switched in a tight loop rather than
// individual pin assignments or clunky lists.
//
enum pinIdxToPinNumMap {
Z80_A0 = 0,
Z80_A1 = 1,
Z80_A2 = 2,
Z80_A3 = 3,
Z80_A4 = 4,
Z80_A5 = 5,
Z80_A6 = 6,
Z80_A7 = 7,
Z80_A8 = 8,
Z80_A9 = 9,
Z80_A10 = 10,
Z80_A11 = 11,
Z80_A12 = 12,
Z80_A13 = 13,
Z80_A14 = 14,
Z80_A15 = 15,
Z80_A16 = 16,
Z80_A17 = 17,
Z80_A18 = 18,
Z80_A19 = 19,
Z80_A20 = 20,
Z80_A21 = 21,
Z80_A22 = 22,
Z80_A23 = 23,
Z80_D0 = 24,
Z80_D1 = 25,
Z80_D2 = 26,
Z80_D3 = 27,
Z80_D4 = 28,
Z80_D5 = 29,
Z80_D6 = 30,
Z80_D7 = 31,
Z80_IORQ = 32,
Z80_MREQ = 33,
Z80_RD = 34,
Z80_WR = 35,
Z80_WAIT = 36,
Z80_BUSACK = 37,
Z80_NMI = 38,
Z80_INT = 39,
Z80_RESET = 40,
MB_SYSCLK = 41,
CTL_SVCREQ = 42,
CTL_MBSEL = 43,
CTL_BUSRQ = 44,
CTL_RFSH = 45,
CTL_HALT = 46,
CTL_M1 = 47,
CTL_WAIT = 48,
CTL_CLK = 49,
CTL_BUSACK = 50
};
// Possible control modes that the K64F can be in, do nothing where the Z80 runs normally, control the Z80 and mainboard, or control the Z80 and tranZPUter.
enum CTRL_MODE {
Z80_RUN = 0,
TRANZPUTER_ACCESS = 1,
MAINBOARD_ACCESS = 2
};
// Possible targets the K64F can read from/write to.
enum TARGETS {
MAINBOARD = 0,
TRANZPUTER = 1,
FPGA = 2
};
// Possible bus directions that the K64F can setup for controlling the Z80.
enum BUS_DIRECTION {
READ = 0,
WRITE = 1,
TRISTATE = 2
};
// Possible video frames stored internally.
//
enum VIDEO_FRAMES {
SAVED = 0,
WORKING = 1
};
// Possible machines the tranZPUter can be hosted on and can emulate.
//
enum MACHINE_TYPES {
MZ80K = 0x00, // Machine = MZ-80K.
MZ80C = 0x01, // Machine = MZ-80C.
MZ1200 = 0x02, // Machine = MZ-1200.
MZ80A = 0x03, // Machine = MZ-80A.
MZ700 = 0x04, // Machine = MZ-700.
MZ800 = 0x05, // Machine = MZ-800.
MZ80B = 0x06, // Machine = MZ-80B.
MZ2000 = 0x07 // Machine = MZ-2000.
};
// Get and Set flags within the CPLD config and status registers.
//
enum CPLD_FLAGS {
VIDEO_FPGA = 0x08, // Bit to test for available functionality or enabling of the FPGA video hardware.
CPLD_VERSION = 0xE0 // CPLD version mask bits.
};
// Types of file which have handlers and can be processed.
//
enum FILE_TYPE {
MZF = 0, // Sharp MZF tape image files.
CAS = 1, // BASIC CASsette image files.
BAS = 2, // BASic ASCII text script files.
ALL = 10, // All files to be considered.
ALLFMT = 11 // Special case for directory listings, all files but truncated and formatted.
};
// Structure to define a Sharp MZ80A MZF directory structure. This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
//
typedef struct __attribute__((__packed__)) {
uint8_t attr; // MZF attribute describing the file.
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
uint16_t fileSize; // Size of file.
uint16_t loadAddr; // Load address for the file.
uint16_t execAddr; // Execution address where the Z80 starts processing.
uint8_t comment[MZF_COMMENT_LEN]; // Text comment field but often contains a startup machine code program.
} t_svcDirEnt;
// Structure to define a compacted Sharp MZ80A MZF directory structure (no comment) for use in directory listings.
// This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
//
typedef struct __attribute__((__packed__)) {
uint8_t attr; // MZF attribute describing the file.
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
uint16_t fileSize; // Size of file.
uint16_t loadAddr; // Load address for the file.
uint16_t execAddr; // Execution address where the Z80 starts processing.
uint8_t filler[MZF_FILLER_LEN]; // Filler to pad to a power of 2 length.
} t_svcCmpDirEnt;
// Structure to hold the map betwen an SD filename and the Sharp file it contains. The file is an MZF format file with a 128 byte header
// and this header contains the name understood on the Sharp MZ80A.
//
typedef struct __attribute__((__packed__)) {
uint8_t *sdFileName; // Name of file on the SD card.
t_svcCmpDirEnt mzfHeader; // Compact Sharp header data of this file.
} t_sharpToSDMap;
// Structure to define the control information for a CP/M disk drive.
//
typedef struct {
uint8_t *fileName; // FQFN of the CPM disk image file.
uint32_t lastTrack; // Track of last successful operation.
uint32_t lastSector; // Sector of last successful operation.
FIL File; // Opened file handle of the CPM disk image.
} t_cpmDrive;
// Structure to define which CP/M drives are added to the system, mapping a number from CP/M into a record containing the details of the file on the SD card.
//
typedef struct {
t_cpmDrive *drive[CPM_MAX_DRIVES]; // 1:1 map of CP/M drive number to an actual file on the SD card.
} t_cpmDriveMap;
// Structure to hold a map of an entire directory of files on the SD card and their associated Sharp MZ0A filename.
typedef struct __attribute__((__packed__)) {
uint8_t valid; // Is this mapping valid?
uint8_t entries; // Number of entries in cache.
uint8_t type; // Type of file being cached.
char directory[TZSVC_DIRNAME_SIZE]; // Directory this mapping is associated with.
union {
t_sharpToSDMap *mzfFile[TZSVC_MAX_DIR_ENTRIES]; // File mapping of SD file to its Sharp MZ80A name.
uint8_t *sdFileName[TZSVC_MAX_DIR_ENTRIES]; // No mapping for SD filenames, just the file name.
};
} t_dirMap;
// Structure to maintain all MZ700 hardware control information in order to emulate the machine.
//
typedef struct {
uint32_t config; // Compacted control register, 31:19 = reserved, 18 = Inhibit mode, 17 = Upper D000:FFFF is RAM (=1), 16 = Lower 0000:0FFF is RAM (=1), 15:8 = old memory mode, 7:0 = current memory mode.
//uint8_t memoryMode; // The memory mode the MZ700 is currently running under, this is determined by the memory control commands from the MZ700.
//uint8_t lockMemoryMode; // The preserved memory mode when entering the locked state.
//uint8_t inhibit; // The inhibit flag, blocks the upper 0xD000:0xFFFF region from being accessed, affects the memoryMode temporarily.
//uint8_t update; // Update flag, indicates to the ISR that a memory mode update is needed.
//uint8_t b0000; // Block 0000:0FFF mode.
//uint8_t bD000; // Block D000:FFFF mode.
} t_mz700;
// Structure to maintain all MZ-80B hardware control information in oder to emulate the machine as near as possible.
typedef struct {
uint32_t config; // Compacted control register, 31:19 = reserved, 18 = Inhibit mode, 17 = Upper D000:FFFF is RAM (=1), 16 = Lower 0000:0FFF is RAM (=1), 15:8 = old memory mode, 7:0 = current memory mode.
} t_mz80b;
// Structure to maintain all the control and management variables of the Z80 and underlying hardware so that the state of run is well known by any called method.
//
typedef struct {
#if !defined(__APP__) || defined(__TZFLUPD__)
uint32_t svcControlAddr; // Address of the service control record within the 512K static RAM bank.
uint8_t refreshAddr; // Refresh address for times when the K64F must issue refresh cycles on the Z80 bus.
uint8_t disableRefresh; // Disable refresh if the mainboard DRAM isnt being used.
uint8_t runCtrlLatch; // Latch value the Z80 is running with.
uint8_t curCtrlLatch; // Latch value set during tranZPUter access of the Z80 bus.
uint8_t holdZ80; // A flag to hold the Z80 bus when multiple transactions need to take place.
uint8_t videoRAM[2][2048]; // Two video memory buffer frames, allows for storage of original frame in [0] and working frame in [1].
uint8_t attributeRAM[2][2048]; // Two attribute memory buffer frames, allows for storage of original frame in [0] and working frame in [1].
enum CTRL_MODE ctrlMode; // Mode of control, ie normal Z80 Running, controlling mainboard, controlling tranZPUter.
enum BUS_DIRECTION busDir; // Direction the bus has been configured for.
enum MACHINE_TYPES hostType; // The underlying host machine, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B
enum MACHINE_TYPES machineMode; // Machine compatibility, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B
t_mz700 mz700; // MZ700 emulation control to detect IO commands and adjust the memory map accordingly.
t_mz80b mz80b; // MZ-80B emulation control to detect IO commands and adjust the memory map and I/O forwarding accordingly.
uint8_t resetEvent; // A Z80_RESET event occurred, probably user pressing RESET button.
uint8_t svcRequest; // A service request has been made by the Z80 (1).
uint8_t sysRequest; // A system request has been made by the Z80 (1).
uint8_t ioAddr; // Address of a Z80 IO instruction.
uint8_t ioEvent; // Event flag to indicate that an IO instruction was captured.
uint8_t ioData; // Data of a Z80 IO instruction.
uint8_t memorySwap; // A memory Swap event has occurred, 0000-0FFF -> C000-CFFF (1), or C000-CFFF -> 0000-0FFF (0)
uint8_t crtMode; // A CRT event has occurred, Normal mode (0) or Reverse Mode (1)
uint8_t scroll; // Hardware scroll offset.
volatile uint32_t portA; // ISR store of GPIO Port A used for signal decoding.
volatile uint32_t portB; // ISR store of GPIO Port B used for signal decoding.
volatile uint32_t portC; // ISR store of GPIO Port C used for signal decoding.
volatile uint32_t portD; // ISR store of GPIO Port D used for signal decoding.
volatile uint32_t portE; // ISR store of GPIO Port E used for signal decoding.
#endif
} t_z80Control;
// Structure to maintain higher level OS control and management variables typically used for TZFS and CPM.
//
typedef struct {
uint8_t tzAutoBoot; // Autoboot the tranZPUter into TZFS mode.
t_dirMap dirMap; // Directory map of SD filenames to Sharp MZ80A filenames.
t_cpmDriveMap cpmDriveMap; // Map of file number to an open SD disk file to be used as a CPM drive.
uint8_t *lastFile; // Last file loaded - typically used for CPM to reload itself.
} t_osControl;
// Structure to contain inter CPU communications memory for command service processing and results.
// Typically the z80 places a command into the structure in it's memory space and asserts an I/O request,
// the K64F detects the request and reads the lower portion of the struct from z80 memory space,
// determines the command and then either reads the remainder or writes to the remainder. This struct
// exists in both the z80 and K64F domains and data is sync'd between them as needed.
//
typedef struct __attribute__((__packed__)) {
uint8_t cmd; // Command request.
uint8_t result; // Result code. 0xFE - set by Z80, command available, 0xFE - set by K64F, command ack and processing. 0x00-0xF0 = cmd complete and result of processing.
union {
uint8_t dirSector; // Virtual directory sector number.
uint8_t fileSector; // Sector within open file to read/write.
uint8_t vDriveNo; // Virtual or physical SD card drive number.
};
union {
struct {
uint16_t trackNo; // For virtual drives with track and sector this is the track number
uint16_t sectorNo; // For virtual drives with track and sector this is the sector number. NB For LBA access, this is 32bit and overwrites fileNo/fileType which arent used during raw SD access.
};
uint32_t sectorLBA; // For LBA access, this is 32bit and used during raw SD access.
};
uint8_t fileNo; // File number of a file within the last directory listing to open/update.
uint8_t fileType; // Type of file being processed.
union {
uint16_t loadAddr; // Load address for ROM/File images which need to be dynamic.
uint16_t saveAddr; // Save address for ROM/File images which need to be dynamic.
uint16_t cpuFreq; // CPU Frequency in KHz - used for setting of the alternate CPU clock frequency.
};
union {
uint16_t loadSize; // Size for ROM/File to be loaded.
uint16_t saveSize; // Size for ROM/File to be saved.
};
uint8_t directory[TZSVC_DIRNAME_SIZE]; // Directory in which to look for a file. If no directory is given default to MZF.
uint8_t filename[TZSVC_FILENAME_SIZE]; // File to open or create.
uint8_t wildcard[TZSVC_WILDCARD_SIZE]; // A basic wildcard pattern match filter to be applied to a directory search.
uint8_t sector[TZSVC_SECTOR_SIZE]; // Sector buffer generally for disk read/write.
} t_svcControl;
// Structure to define all the directory entries which are packed into a single SD sector which is used between the Z80<->K64F.
//
typedef struct __attribute__((__packed__)) {
t_svcDirEnt dirEnt[TZVC_MAX_DIRENT_BLOCK]; // Fixed number of directory entries per sector/block.
} t_svcDirBlock;
// Structure to hold compacted directory entries which are packed into a single SD sector which is used between the Z80<->K64F.
//
typedef struct __attribute__((__packed__)) {
t_svcCmpDirEnt dirEnt[TZVC_MAX_CMPCT_DIRENT_BLOCK];// Fixed number of compacted directory entries per sector/block.
} t_svcCmpDirBlock;
// Mapping table from Sharp MZ80A Ascii to real Ascii.
//
typedef struct {
uint8_t asciiCode;
} t_asciiMap;
// Application execution constants.
//
// For the ARM Cortex-M compiler, the standard filestreams in an app are set by the CRT0 startup code,
// the original reentrant definition is undefined as it is not needed in the app.
#if defined __APP__ && defined __K64F__
#undef stdout
#undef stdin
#undef stderr
FILE *stdout;
FILE *stdin;
FILE *stderr;
#endif
// References to variables within the main library code.
extern volatile uint32_t *ioPin[MAX_TRANZPUTER_PINS];
extern uint8_t pinMap[MAX_TRANZPUTER_PINS];
// Prototypes.
//
#if defined __APP__
void yield(void);
#endif
void setupZ80Pins(uint8_t, volatile uint32_t *);
void resetZ80(uint8_t);
uint8_t reqZ80Bus(uint32_t);
uint8_t reqMainboardBus(uint32_t);
uint8_t reqTranZPUterBus(uint32_t, enum TARGETS);
void setupSignalsForZ80Access(enum BUS_DIRECTION);
void releaseZ80(void);
void refreshZ80(void);
void setCtrlLatch(uint8_t);
uint32_t setZ80CPUFrequency(float, uint8_t);
uint8_t copyFromZ80(uint8_t *, uint32_t, uint32_t, enum TARGETS);
uint8_t copyToZ80(uint32_t, uint8_t *, uint32_t, enum TARGETS);
uint8_t writeZ80Memory(uint32_t, uint8_t, enum TARGETS);
uint8_t readZ80Memory(uint32_t);
uint8_t outZ80IO(uint32_t, uint8_t);
uint8_t inZ80IO(uint32_t);
uint8_t writeZ80IO(uint32_t, uint8_t, enum TARGETS);
uint8_t readZ80IO(uint32_t, enum TARGETS);
void fillZ80Memory(uint32_t, uint32_t, uint8_t, enum TARGETS);
void captureVideoFrame(enum VIDEO_FRAMES, uint8_t);
void refreshVideoFrame(enum VIDEO_FRAMES, uint8_t, uint8_t);
FRESULT loadVideoFrameBuffer(char *, enum VIDEO_FRAMES);
FRESULT saveVideoFrameBuffer(char *, enum VIDEO_FRAMES);
char *getVideoFrame(enum VIDEO_FRAMES);
char *getAttributeFrame(enum VIDEO_FRAMES);
FRESULT loadZ80Memory(const char *, uint32_t, uint32_t, uint32_t, uint32_t *, enum TARGETS, uint8_t);
FRESULT saveZ80Memory(const char *, uint32_t, uint32_t, t_svcDirEnt *, enum TARGETS);
FRESULT loadMZFZ80Memory(const char *, uint32_t, uint32_t *, enum TARGETS, uint8_t);
// Getter/Setter methods!
uint8_t isZ80Reset(void);
uint8_t isZ80MemorySwapped(void);
uint8_t getZ80IO(uint8_t *);
void clearZ80Reset(void);
void convertSharpFilenameToAscii(char *, char *, uint8_t);
// tranZPUter OS i/f methods.
uint8_t setZ80SvcStatus(uint8_t);
void svcSetDefaults(enum FILE_TYPE);
uint8_t svcReadDir(uint8_t, enum FILE_TYPE);
uint8_t svcFindFile(char *, char *, uint8_t, enum FILE_TYPE);
uint8_t svcReadDirCache(uint8_t, enum FILE_TYPE);
uint8_t svcFindFileCache(char *, char *, uint8_t, enum FILE_TYPE);
uint8_t svcCacheDir(const char *, enum FILE_TYPE, uint8_t);
uint8_t svcReadFile(uint8_t, enum FILE_TYPE);
uint8_t svcWriteFile(uint8_t, enum FILE_TYPE);
uint8_t svcLoadFile(enum FILE_TYPE);
uint8_t svcSaveFile(enum FILE_TYPE);
uint8_t svcEraseFile(enum FILE_TYPE);
uint8_t svcAddCPMDrive(void);
uint8_t svcReadCPMDrive(void);
uint8_t svcWriteCPMDrive(void);
uint32_t getServiceAddr(void);
void processServiceRequest(void);
uint8_t loadBIOS(const char *biosFileName, uint8_t machineMode, uint32_t loadAddr);
void hardResetTranZPUter(void);
void loadTranZPUterDefaultROMS(uint8_t);
void tranZPUterControl(void);
uint8_t testTZFSAutoBoot(void);
void setHost(void);
void setupTranZPUter(void);
void testRoutine(void);
#if defined __APP__
int memoryDumpZ80(uint32_t, uint32_t, uint32_t, uint8_t, enum TARGETS);
#endif
// Debug methods.
#if defined __APP__ && defined __TZPU_DEBUG__
void displaySignals(void);
#endif
#ifdef __cplusplus
}
#endif
#endif // TRANZPUTER_H

View File

@@ -9,6 +9,7 @@
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// Feb 2021 - Replaced getopt_long with optparse as it is buggy and crashes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -41,7 +42,6 @@
#include <usb_serial.h>
#include <core_pins.h>
#include <Arduino.h>
#include <getopt.h>
#include "k64f_soc.h"
#include <../../libraries/include/stdmisc.h>
#elif defined(__ZPU__)
@@ -65,6 +65,12 @@
#else
#error OS not defined, use __ZPUTA__ or __ZOS__
#endif
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include <optparse.h>
//
#include <app.h>
#include <tranzputer.h>
@@ -74,8 +80,8 @@
#include <tools.c>
// Version info.
#define VERSION "v1.1"
#define VERSION_DATE "10/12/2020"
#define VERSION "v1.2"
#define VERSION_DATE "21/02/2021"
#define APP_NAME "TZCLEAR"
// Simple help screen to remmber how this utility works!!
@@ -118,7 +124,6 @@ uint32_t app(uint32_t param1, uint32_t param2)
int mainboard_flag = 0;
int verbose_flag = 0;
int opt;
int option_index = 0;
long val = 0;
char *argv[20];
char *ptr = strtok((char *)param1, " ");
@@ -141,22 +146,24 @@ uint32_t app(uint32_t param1, uint32_t param2)
argv[argc] = 0;
// Define parameters to be processed.
static struct option long_options[] =
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", no_argument, 0, 'h'},
{"start", required_argument, 0, 'a'},
{"end", required_argument, 0, 'e'},
{"size", required_argument, 0, 's'},
{"byte", required_argument, 0, 'b'},
{"fpga", no_argument, 0, 'f'},
{"mainboard", no_argument, 0, 'm'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
{"help", 'h', OPTPARSE_NONE},
{"start", 'a', OPTPARSE_REQUIRED},
{"end", 'e', OPTPARSE_REQUIRED},
{"size", 's', OPTPARSE_REQUIRED},
{"byte", 'b', OPTPARSE_REQUIRED},
{"fpga", 'f', OPTPARSE_NONE},
{"mainboard", 'm', OPTPARSE_NONE},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
while((opt = getopt_long(argc, argv, ":hs:e:s:fmv", long_options, &option_index)) != -1)
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
@@ -173,36 +180,36 @@ uint32_t app(uint32_t param1, uint32_t param2)
break;
case 'a':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(5);
}
startAddr = (uint32_t)val;
break;
case 'e':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(6);
}
endAddr = (uint32_t)val;
break;
case 's':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(7);
}
memSize = (uint32_t)val;
break;
case 'b':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(6);
}
byte = (uint8_t)val;
@@ -212,12 +219,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
verbose_flag = 1;
break;
case ':':
printf("Option %s needs a value\n", argv[optind-1]);
break;
case '?':
printf("Unknown option: %s, ignoring!\n", argv[optind-1]);
break;
case '?':
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}

View File

@@ -8,9 +8,10 @@
// frequency but when the secondary clock is eaabled, it is used when using tranZPUter
// onboard hardware such as the static RAM.
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2021 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// Feb 2021 - Replaced getopt_long with optparse as it is buggy and crashes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -43,7 +44,6 @@
#include <usb_serial.h>
#include <core_pins.h>
#include <Arduino.h>
#include <getopt.h>
#include "k64f_soc.h"
#include <../../libraries/include/stdmisc.h>
#elif defined(__ZPU__)
@@ -67,6 +67,12 @@
#else
#error OS not defined, use __ZPUTA__ or __ZOS__
#endif
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include <optparse.h>
//
#include <app.h>
#include <tranzputer.h>
@@ -76,8 +82,8 @@
#include <tools.c>
// Version info.
#define VERSION "v1.0"
#define VERSION_DATE "08/06/2020"
#define VERSION "v1.1"
#define VERSION_DATE "21/02/2021"
#define APP_NAME "TZCLK"
// Simple help screen to remmber how this utility works!!
@@ -115,7 +121,6 @@ uint32_t app(uint32_t param1, uint32_t param2)
int disable_flag = 0;
int verbose_flag = 0;
int opt;
int option_index = 0;
long val = 0;
char *argv[20];
char *ptr = strtok((char *)param1, " ");
@@ -138,19 +143,21 @@ uint32_t app(uint32_t param1, uint32_t param2)
argv[argc] = 0;
// Define parameters to be processed.
static struct option long_options[] =
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", no_argument, 0, 'h'},
{"freq", required_argument, 0, 'f'},
{"enable", no_argument, 0, 'e'},
{"disable", no_argument, 0, 'd'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
{"help", 'h', OPTPARSE_NONE},
{"freq", 'f', OPTPARSE_REQUIRED},
{"enable", 'e', OPTPARSE_NONE},
{"disable", 'd', OPTPARSE_NONE},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
while((opt = getopt_long(argc, argv, ":hs:e:s:mv", long_options, &option_index)) != -1)
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
@@ -167,9 +174,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
break;
case 'f':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(5);
}
cpuFreq = (uint32_t)val;
@@ -179,12 +186,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
verbose_flag = 1;
break;
case ':':
printf("Option %s needs a value\n", argv[optind-1]);
break;
case '?':
printf("Unknown option: %s, ignoring!\n", argv[optind-1]);
break;
case '?':
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}

View File

@@ -6,9 +6,10 @@
// Description: A TranZPUter helper utility, allowing the realtime display of the tranZPUter
// or host mainboard memory.
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2021 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// Feb 2021 - Replaced getopt_long with optparse as it is buggy and crashes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -41,7 +42,6 @@
#include <usb_serial.h>
#include <core_pins.h>
#include <Arduino.h>
#include <getopt.h>
#include "k64f_soc.h"
#include <../../libraries/include/stdmisc.h>
#elif defined(__ZPU__)
@@ -65,6 +65,12 @@
#else
#error OS not defined, use __ZPUTA__ or __ZOS__
#endif
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include <optparse.h>
//
#include <app.h>
#include <tranzputer.h>
@@ -74,8 +80,8 @@
#include <tools.c>
// Version info.
#define VERSION "v1.1"
#define VERSION_DATE "10/12/2020"
#define VERSION "v1.2"
#define VERSION_DATE "21/02/2021"
#define APP_NAME "TZDUMP"
// Simple help screen to remmber how this utility works!!
@@ -117,7 +123,6 @@ uint32_t app(uint32_t param1, uint32_t param2)
int mainboard_flag = 0;
int verbose_flag = 0;
int opt;
int option_index = 0;
long val = 0;
char *argv[20];
char *ptr = strtok((char *)param1, " ");
@@ -140,21 +145,23 @@ uint32_t app(uint32_t param1, uint32_t param2)
argv[argc] = 0;
// Define parameters to be processed.
static struct option long_options[] =
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", no_argument, 0, 'h'},
{"start", required_argument, 0, 'a'},
{"end", required_argument, 0, 'e'},
{"size", required_argument, 0, 's'},
{"fpga", no_argument, 0, 'f'},
{"mainboard", no_argument, 0, 'm'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
{"help", 'h', OPTPARSE_NONE},
{"start", 'a', OPTPARSE_REQUIRED},
{"end", 'e', OPTPARSE_REQUIRED},
{"size", 's', OPTPARSE_REQUIRED},
{"fpga", 'f', OPTPARSE_NONE},
{"mainboard", 'm', OPTPARSE_NONE},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
while((opt = getopt_long(argc, argv, ":hs:e:s:fmv", long_options, &option_index)) != -1)
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
@@ -171,27 +178,27 @@ uint32_t app(uint32_t param1, uint32_t param2)
break;
case 'a':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(5);
}
startAddr = (uint32_t)val;
break;
case 'e':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(6);
}
endAddr = (uint32_t)val;
break;
case 's':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(7);
}
memSize = (uint32_t)val;
@@ -201,12 +208,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
verbose_flag = 1;
break;
case ':':
printf("Option %s needs a value\n", argv[optind-1]);
break;
case '?':
printf("Unknown option: %s, ignoring!\n", argv[optind-1]);
break;
case '?':
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}

86
apps/tzflupd/Makefile Executable file
View File

@@ -0,0 +1,86 @@
#########################################################################################################
##
## Name: Makefile
## Created: July 2019
## Author(s): Philip Smart
## Description: App Makefile - Build an App for the ZPU Test Application (zputa) or the zOS
## operating system.
## This makefile builds an app which is stored on an SD card and called by ZPUTA/zOS
## The app is for testing some component where the code is not built into ZPUTA or
## a user application for zOS.
##
## Credits:
## Copyright: (c) 2019-21 Philip Smart <philip.smart@net2net.org>
##
## History: July 2019 - Initial Makefile created for template use.
## April 2020 - Added K64F as an additional target and resplit ZPUTA into zOS.
##
## Notes: Optional component enables:
## USELOADB - The Byte write command is implemented in hw#sw so use it.
## USE_BOOT_ROM - The target is ROM so dont use initialised data.
## MINIMUM_FUNTIONALITY - Minimise functionality to limit code size.
##
#########################################################################################################
## This source file is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This source file is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
#########################################################################################################
APP_NAME = tzflupd
APP_DIR = $(CURDIR)/..
APP_COMMON_DIR = $(CURDIR)/../common
COMMON_DIR = $(CURDIR)/../../common
BASEDIR = ../../..
TEENSYDIR = ../../teensy3/
# Override values given by parent make for this application as its memory usage differs from the standard app.
ifeq ($(__K64F__),1)
#override HEAPADDR = 0x2002f000
#override HEAPSIZE = 0x00000000
#override STACKADDR = 0x2002f000
#override STACKSIZE = 0x00000000
# Modules making up tzflupd.
APP_C_SRC = $(APP_COMMON_DIR)/fsl_flash.c
# APP_C_SRC = $(COMMON_DIR)/tranzputer.c
CFLAGS = -D CPU_MK64FX512VLL12 -D __TZFLUPD__ -mthumb -fno-builtin -ffunction-sections -fdata-sections -D__MK64FX512__ -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 #--save-temps
CPPFLAGS =
LDFLAGS =
LIBS =
else
# Modules making up tzflupd.
APP_C_SRC = #$(APP_COMMON_DIR)/sysutils.c $(APP_COMMON_DIR)/ctypelocal.c
CFLAGS =
CPPFLAGS =
LDFLAGS = -nostdlib
LIBS = -lumansi-zpu -limath-zpu
endif
# Filter out the standard HEAP address and size, replacing with the ones required for this application.
# Useful for sub-makes
FILTER1 = $(filter-out $(filter HEAPADDR=%,$(MAKEFLAGS)), $(MAKEFLAGS))
FILTER2 = $(filter-out $(filter HEAPSIZE=%,$(FILTER1)), $(FILTER1))
NEWMAKEFLAGS = $(FILTER2) HEAPADDR=$(HEADADDR) HEAPSIZE=$(HEAPSIZE)
ifeq ($(__K64F__),1)
include $(APP_DIR)/Makefile.k64f
else
# There currently is no code for the ZPU, all development being done on the K64F for this app.
all:
clean:
install:
endif

380
apps/tzflupd/tzflupd.c Normal file
View File

@@ -0,0 +1,380 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: tzdump.c
// Created: Jan 2021
// Author(s): Philip Smart
// Description: A TranZPUter helper utility to update the program in the K64F ARM Processor. This
// application takes a binary and flashes it into the K64F Flash Memory in order to
// update zOS/ZPUTA or flash any other program (NB. flashing any other program may
// need an external OpenSDA programmer to reprogram the K64F with zOS).
// Credits:
// Copyright: (c) 2019-2021 Philip Smart <philip.smart@net2net.org>
//
// History: Jan 2021 - Initial write of the TranZPUter software using NXP/Freescale flash
// driver source.
// Feb 2021 - Getopt too buggy with long arguments so replaced with optparse.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// For the Freescale driver code, please see the license at the top of the driver source file.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__K64F__)
#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include "k64f_soc.h"
#include <../../libraries/include/stdmisc.h>
#elif defined(__ZPU__)
#include <stdint.h>
#include <stdio.h>
#include "zpu_soc.h"
#include <stdlib.h>
#include <ctype.h>
#include <stdmisc.h>
#else
#error "Target CPU not defined, use __ZPU__ or __K64F__"
#endif
#include "interrupts.h"
#include "ff.h" /* Declarations of FatFs API */
//#include "utils.h"
//
#if defined __ZPUTA__
#include "zputa_app.h"
#elif defined __ZOS__
#include "zOS_app.h"
#else
#error OS not defined, use __ZPUTA__ or __ZOS__
#endif
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include <optparse.h>
//
#include <app.h>
#if defined(__K64F__)
#include <tranzputer_m.h>
#include "tzflupd.h"
#include "fsl_flash.h"
#endif
// Utility functions.
//#include <tools.c>
// Version info.
#define VERSION "v1.1"
#define VERSION_DATE "21/02/2021"
#define APP_NAME "TZFLUPD"
// Global scope variables.
FATFS diskHandle;
char buffer[512];
uint8_t FLASH_PROTECTION_SIGNATURE[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0xf9, 0xff, 0xff};
// Simple help screen to remmber how this utility works!!
//
void usage(void)
{
printf("%s %s\n", APP_NAME, VERSION);
printf("\nCommands:-\n");
printf(" -h | --help This help text.\n");
printf(" -f | --file Binary file to upload and flash into K64F.\n");
printf("\nOptions:-\n");
printf(" -v | --verbose Output more messages.\n");
printf("\nExamples:\n");
printf(" tzflupd -f zOS_22012021_001.bin --verbose # Upload and program the zOS_22012021_001.bin file into the K64F flash memory.\n");
}
// Method to initialise the SD card and mount the first partition. The file we need to upload into the K64F Flash RAM is stored on this card.
//
FRESULT initSDCard(void)
{
// Locals.
//
FRESULT result = FR_NOT_ENABLED;
// Make a complete initialisation as we are using a new Fat FS instance.
//
if(!disk_initialize(0, 1))
{
sprintf(buffer, "0:");
result = f_mount(&diskHandle, buffer, 0);
}
return(result);
}
// Main entry and start point of a zOS/ZPUTA Application. Only 2 parameters are catered for and a 32bit return code, additional parameters can be added by changing the appcrt0.s
// startup code to add them to the stack prior to app() call.
//
// Return code for the ZPU is saved in _memreg by the C compiler, this is transferred to _memreg in zOS/ZPUTA in appcrt0.s prior to return.
// The K64F ARM processor uses the standard register passing conventions, return code is stored in R0.
//
uint32_t app(uint32_t param1, uint32_t param2)
{
// Initialisation.
//
int argc = 0;
int help_flag = 0;
int uploadFNLen = 0;
int verbose_flag = 0;
int opt;
int updateFNLen = 0;
long val = 0;
char *argv[20];
char *ptr = strtok((char *)param1, " ");
char updateFile[32];
uint32_t fileSize;
uint32_t readSize;
uint32_t sizeToRead;
uint32_t bytesProcessed;
flash_config_t flashDriver; // Flash driver Structure
status_t flashResult; // Return code from each flash driver function
FRESULT fResult; // Fat FS result.
FIL fileHandle; // File Handle.
// If the invoking command is given, add it to argv at the start.
//
if(param2 != 0)
{
argv[argc++] = (char *)param2;
}
// Now convert the parameter line into argc/argv suitable for getopt to use.
while (ptr && argc < 20-1)
{
argv[argc++] = ptr;
ptr = strtok(0, " ");
}
argv[argc] = 0;
// Define parameters to be processed.
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", 'h', OPTPARSE_NONE},
{"file", 'f', OPTPARSE_REQUIRED},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
case 'h':
help_flag = 1;
break;
case 'f':
strcpy(updateFile, options.optarg);
updateFNLen = strlen(updateFile);
break;
case 'v':
verbose_flag = 1;
break;
case '?':
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}
// Validate the input.
if(help_flag == 1)
{
usage();
return(0);
}
if(updateFNLen == 0)
{
printf("Update file needs to be specified.\n");
return(1);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
// As the kernel will be erased we need to assume kernel functionality so initialise kernel features, such as the SD card here as we use them locally.
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
if((fResult=initSDCard()) != FR_OK)
{
printf("ERROR: Failed to re-initialise the SD card, cannot continue.\n");
return(10);
}
// Initialise the flash driver.
memset(&flashDriver, 0, sizeof(flash_config_t));
flashResult = FLASH_Init(&flashDriver);
if (kStatus_FLASH_Success != flashResult)
{
printf("Error: Failed to initialize Flash memory driver!\n");
return(11);
}
// Try and open the source file.
fResult = f_open(&fileHandle, updateFile, FA_OPEN_EXISTING | FA_READ);
// Get the size of the file.
if(fResult == FR_OK)
fResult = f_lseek(&fileHandle, f_size(&fileHandle));
if(fResult == FR_OK)
fileSize = (uint32_t)f_tell(&fileHandle);
if(fResult == FR_OK)
fResult = f_lseek(&fileHandle, 0);
// Verify that the binary is a K64F program. Do this by comparing the protection area which is static and non changing.
//
fResult = f_lseek(&fileHandle, FLASH_PROTECTION_START_ADDR);
if(fResult == FR_OK)
fResult = f_read(&fileHandle, buffer, FLASH_PROTECTION_SIZE, &readSize);
if(fResult == FR_OK)
{
for(int idx=0; idx < FLASH_PROTECTION_SIZE; idx++)
{
if(buffer[idx] != FLASH_PROTECTION_SIGNATURE[idx])
{
printf("Error: Update file doesnt look like a valid K64F program binary, aborting!\n");
return(12);
}
}
fResult = f_lseek(&fileHandle, 0);
}
// If all ok, indicate file has been opened then prepare to read and flash.
if(fResult == FR_OK)
{
printf("Opened file: %s, size=%ld bytes\n", updateFile, fileSize);
printf("Flash will now commence, no further output if core kernel drivers being updated.\nPlease reset after 30 seconds if no further message seen...\n");
// Slight delay to allow the output to flush to the user serial console.
uint32_t startTime = G->millis;
while((G->millis - startTime) < 5000);
// Enter a loop, reading sector at a time from the SD card and flashing it into the Flash RAM.
//
bytesProcessed = 0;
do {
sizeToRead = (fileSize-bytesProcessed) > SECTOR_SIZE ? SECTOR_SIZE : fileSize - bytesProcessed;
fResult = f_read(&fileHandle, buffer, sizeToRead, &readSize);
if (fResult || readSize == 0) break; /* error or eof */
// If a sector isnt full, ie. last sector, pad with 0xFF.
//
if(readSize != SECTOR_SIZE)
{
for(uint16_t idx=readSize; idx < SECTOR_SIZE; idx++) { buffer[idx] = 0xFF; }
}
// Flash the sector into the correct location governed by the bytes already processed. We flash in 8 byte rows, we could flash full sectors but need to avoid the
// device protection region. The only downside of flashing in 8 byte chunks is the call overheads but these are negligible on the K64F.
//
__disable_irq();
// Now program the sectors worth of data.
for(uint32_t idx=bytesProcessed; idx < bytesProcessed+SECTOR_SIZE; idx+=8)
{
// Skip the device protection bits, we dont want to overwrite these, should only be programed whenan external OpenSDA is connected.
if(idx < FLASH_PROTECTION_START_ADDR && idx > FLASH_PROTECTION_START_ADDR+FLASH_PROTECTION_SIZE-1)
{
// If no previous errors, program the next 8 bytes.
flashResult = FLASH_Erase(&flashDriver, idx, 8, kFLASH_ApiEraseKey);
if(flashResult == kStatus_FLASH_Success)
flashResult = FLASH_Program(&flashDriver, idx, (uint32_t*)buffer[idx], 8);
}
}
__enable_irq();
// Update the address/bytes processed count.
bytesProcessed += SECTOR_SIZE;
} while(bytesProcessed < fileSize && flashResult == kStatus_FLASH_Success);
// Verbose output.
if(verbose_flag)
printf("Bytes processed:%ld\n", bytesProcessed);
// Success in programming, clear rest of flash RAM.
if(flashResult == kStatus_FLASH_Success)
{
// Move to the next full sector as erase operates on sector boundaries.
bytesProcessed = bytesProcessed + (bytesProcessed % FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE);
// Verbose output.
if(verbose_flag)
printf("Clearing remainder of flash:%ld bytes\n", ((uint32_t)flashDriver.PFlashTotalSize-bytesProcessed));
// Erase remainder of the device, caters for previous image being larger than update.
__disable_irq();
flashResult = FLASH_Erase(&flashDriver, bytesProcessed, ((uint32_t)flashDriver.PFlashTotalSize-bytesProcessed), kFLASH_ApiEraseKey);
__enable_irq();
}
// Any errors, report (assuming kernel still intact) and hang.
if (flashResult != kStatus_FLASH_Success)
{
// This message may not be seen if the kernel has been wiped. put here incase of error before erase.
printf("Error: Failed to program new upgrade into Flash memory area!\n");
printf(" Reset device. If device doesnt restart use an OpenSDA or JTAG programmer to reprogram.\n\n");
while(1) {};
}
// Debug - place a message in an unused sector which can be checked to see if programming worked.
if(0)
{
sprintf(buffer, "FLASH PROGRAMMING CHECK MESSAGE");
for(uint16_t idx=strlen(buffer); idx < SECTOR_SIZE; idx++) { buffer[idx] = 0x00; }
__disable_irq();
flashResult = FLASH_Erase(&flashDriver, bytesProcessed+4096, SECTOR_SIZE, kFLASH_ApiEraseKey);
flashResult = FLASH_Program(&flashDriver, bytesProcessed+4096, (uint32_t*)buffer, SECTOR_SIZE);
__enable_irq();
}
// Just in case we have output connectivity. If the update doesnt change too much then we should maintain connectivity with the USB.
if(flashResult != kStatus_FLASH_Success)
{
printf("Error: Flash programming failed, addr:%ld, result:%d\n", bytesProcessed, flashResult);
}
// Tidy up for exit.
f_close(&fileHandle);
} else
{
printf("Error: Failed to read update file:%s, aborting!\n", updateFile);
return(13);
}
printf("Programming successful, please reset the device to activate update!\n");
return(0);
}
#ifdef __cplusplus
}
#endif

86
apps/tzflupd/tzflupd.h Executable file
View File

@@ -0,0 +1,86 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: tzflupd.h
// Created: Jan 2021
// Author(s): Philip Smart
// Description: A TranZPUter helper utility to update the program in the K64F ARM Processor. This
// application takes a binary and flashes it into the K64F Flash Memory in order to
// update zOS/ZPUTA or flash any other program (NB. flashing any other program may
// need an external OpenSDA programmer to reprogram the K64F with zOS).
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
//
// History: Jan 2021 - Initial write of the TranZPUter software using NXP/Freescale flash
// driver source.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// For the Freescale driver code, please see the license at the top of the driver source file.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef TZFLUPD_H
#define TZFLUPD_H
#ifdef __cplusplus
extern "C" {
#endif
// Constants.
//
#define FLASH_PROTECTION_START_ADDR 0x400
#define FLASH_PROTECTION_SIZE 0x10
// Components to be embedded in the program.
//
// Filesystem components to be embedded in the program.
// Application execution constants.
//
// Macros to enable/disable the K64F interrupts.
//
#define __disable_irq() __asm__ volatile("CPSID i":::"memory");
#define __enable_irq() __asm__ volatile("CPSIE i":::"memory");
// Following two macros pulled from the FRDM code due to a clash between Teensy libraries and their libraries. We depend on the FRDM libraries for the flash routines.
//
/**
brief Get Priority Mask
details Returns the current state of the priority mask bit from the Priority Mask Register.
return Priority Mask value
*/
__attribute__( ( always_inline ) ) inline uint32_t __get_PRIMASK(void)
{
uint32_t result;
__asm__ volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/**
brief Set Priority Mask
details Assigns the given value to the Priority Mask Register.
param [in] priMask Priority Mask
*/
__attribute__( ( always_inline ) ) inline void __set_PRIMASK(uint32_t priMask)
{
__asm__ volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
}
#ifdef __cplusplus
}
#endif
#endif // TZFLUPD_H

View File

@@ -6,9 +6,10 @@
// Description: A TranZPUter helper utility, allowing the realtime setting or reading of the host I/O
// ports.
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2021 Philip Smart <philip.smart@net2net.org>
//
// History: Nov 2020 - Initial write of the TranZPUter software.
// Feb 2021 - Replaced getopt_long with optparse as it is buggy and crashes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -41,7 +42,6 @@
#include <usb_serial.h>
#include <core_pins.h>
#include <Arduino.h>
#include <getopt.h>
#include "k64f_soc.h"
#include <../../libraries/include/stdmisc.h>
#elif defined(__ZPU__)
@@ -65,6 +65,12 @@
#else
#error OS not defined, use __ZPUTA__ or __ZOS__
#endif
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include <optparse.h>
//
#include <app.h>
#include <tranzputer.h>
@@ -74,8 +80,8 @@
#include <tools.c>
// Version info.
#define VERSION "v1.1"
#define VERSION_DATE "08/12/2020"
#define VERSION "v1.2"
#define VERSION_DATE "21/02/2021"
#define APP_NAME "TZIO"
// Simple help screen to remmber how this utility works!!
@@ -115,7 +121,6 @@ uint32_t app(uint32_t param1, uint32_t param2)
int out_flag = 0;
int in_flag = 0;
int opt;
int option_index = 0;
long val = 0;
char *argv[20];
char *ptr = strtok((char *)param1, " ");
@@ -138,20 +143,22 @@ uint32_t app(uint32_t param1, uint32_t param2)
argv[argc] = 0;
// Define parameters to be processed.
static struct option long_options[] =
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", no_argument, 0, 'h'},
{"in", required_argument, 0, 'i'},
{"out", required_argument, 0, 'o'},
{"byte", required_argument, 0, 'b'},
{"mainboard", no_argument, 0, 'm'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
{"help", 'h', OPTPARSE_NONE},
{"in", 'i', OPTPARSE_REQUIRED},
{"out", 'o', OPTPARSE_REQUIRED},
{"byte", 'b', OPTPARSE_REQUIRED},
{"mainboard", 'm', OPTPARSE_NONE},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
while((opt = getopt_long(argc, argv, ":hi:o:b:mv", long_options, &option_index)) != -1)
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
@@ -165,9 +172,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
case 'o':
out_flag = 1;
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(5);
}
ioAddr = (uint32_t)val;
@@ -175,18 +182,18 @@ uint32_t app(uint32_t param1, uint32_t param2)
case 'i':
in_flag = 1;
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(5);
}
ioAddr = (uint32_t)val;
break;
case 'b':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(6);
}
byte = (uint8_t)val;
@@ -196,12 +203,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
verbose_flag = 1;
break;
case ':':
printf("Option %s needs a value\n", argv[optind-1]);
break;
case '?':
printf("Unknown option: %s, ignoring!\n", argv[optind-1]);
break;
case '?':
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}

View File

@@ -6,9 +6,10 @@
// Description: A TranZPUter helper program, responsible for loading images off the SD card into
// memory on the tranZPUter board or host mainboard./
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2021 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// Feb 2021 - Replaced getopt_long with optparse as it is buggy and crashes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -41,7 +42,6 @@
#include <usb_serial.h>
#include <core_pins.h>
#include <Arduino.h>
#include <getopt.h>
#include "k64f_soc.h"
#include <../../libraries/include/stdmisc.h>
#elif defined(__ZPU__)
@@ -65,6 +65,12 @@
#else
#error OS not defined, use __ZPUTA__ or __ZOS__
#endif
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include <optparse.h>
//
#include <app.h>
#include <tranzputer.h>
@@ -74,8 +80,8 @@
#include <tools.c>
// Version info.
#define VERSION "v1.1"
#define VERSION_DATE "10/12/2020"
#define VERSION "v1.2"
#define VERSION_DATE "21/02/2021"
#define APP_NAME "TZLOAD"
// Simple help screen to remmber how this utility works!!
@@ -125,7 +131,6 @@ uint32_t app(uint32_t param1, uint32_t param2)
int verbose_flag = 0;
int video_flag = 0;
int opt;
int option_index = 0;
int uploadFNLen = 0;
int downloadFNLen = 0;
int uploadCnt = 0;
@@ -156,26 +161,28 @@ uint32_t app(uint32_t param1, uint32_t param2)
argv[argc] = 0;
// Define parameters to be processed.
static struct option long_options[] =
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", no_argument, 0, 'h'},
{"download", required_argument, 0, 'd'},
{"upload", required_argument, 0, 'u'},
{"uploadset", required_argument, 0, 'U'},
{"addr", required_argument, 0, 'a'},
{"size", required_argument, 0, 'l'},
{"fpga", no_argument, 0, 'f'},
{"mainboard", no_argument, 0, 'm'},
{"mzf", no_argument, 0, 'z'},
{"swap", no_argument, 0, 's'},
{"verbose", no_argument, 0, 'v'},
{"video", no_argument, 0, 'V'},
{0, 0, 0, 0}
{"help", 'h', OPTPARSE_NONE},
{"download", 'd', OPTPARSE_REQUIRED},
{"upload", 'u', OPTPARSE_REQUIRED},
{"uploadset", 'U', OPTPARSE_REQUIRED},
{"addr", 'a', OPTPARSE_REQUIRED},
{"size", 'l', OPTPARSE_REQUIRED},
{"fpga", 'f', OPTPARSE_NONE},
{"mainboard", 'm', OPTPARSE_NONE},
{"mzf", 'z', OPTPARSE_NONE},
{"swap", 's', OPTPARSE_NONE},
{"verbose", 'v', OPTPARSE_NONE},
{"video", 'V', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
while((opt = getopt_long(argc, argv, ":ha:l:fmvU:Vzsd:u:", long_options, &option_index)) != -1)
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
@@ -196,18 +203,18 @@ uint32_t app(uint32_t param1, uint32_t param2)
break;
case 'a':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(6);
}
memAddr = (uint32_t)val;
break;
case 'l':
if(xatoi(&argv[optind-1], &val) == 0)
if(xatoi(&options.optarg, &val) == 0)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(7);
}
memSize = (uint32_t)val;
@@ -215,20 +222,20 @@ uint32_t app(uint32_t param1, uint32_t param2)
case 'd':
// Data is read from the tranZPUter and stored in the given file.
strcpy(downloadFile, argv[optind-1]);
strcpy(downloadFile, options.optarg);
downloadFNLen = strlen(downloadFile);
break;
case 'u':
// Data is uploaded from the given file into the tranZPUter.
strcpy(uploadFile, argv[optind-1]);
strcpy(uploadFile, options.optarg);
uploadFNLen = strlen(uploadFile);
break;
case 'U':
// Extract an array of <file>:<addr>,... sets for upload.
//
ptr = strtok((char *)argv[optind-1], ",");
ptr = strtok((char *)options.optarg, ",");
while (ptr && uploadCnt < 20-1)
{
uploadArr[uploadCnt++] = ptr;
@@ -253,12 +260,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
mzf_flag = 1;
break;
case ':':
printf("Option %s needs a value\n", argv[optind-1]);
break;
case '?':
printf("Unknown option: %s, ignoring!\n", argv[optind-1]);
break;
case '?':
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}

View File

@@ -6,12 +6,13 @@
// Description: The TranZPUter control program, responsible for booting up and configuring the
// underlying host, providing SD card services and interactive menus.
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2021 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// July 2020 - Another test, a bug with the VHDL on the v2.1 tranZPUter board, so
// needed to output a constant memory mode. The bug turned out to be
// a delayed tri-stating of the bus.
// Feb 2021 - Replaced getopt_long with optparse as it is buggy and crashes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -30,7 +31,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#define TZPU_VERSION "1.0"
#define TZPU_VERSION "1.2"
#ifdef __cplusplus
extern "C" {
@@ -69,6 +70,12 @@
#else
#error OS not defined, use __ZPUTA__ or __ZOS__
#endif
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include <optparse.h>
//
#include <app.h>
#include <tranzputer.h>
@@ -78,8 +85,8 @@
#include <tools.c>
// Version info.
#define VERSION "v1.1"
#define VERSION_DATE "10/12/2020"
#define VERSION "v1.2"
#define VERSION_DATE "21/02/2021"
#define APP_NAME "TZPU"
void testBus(void)
@@ -176,7 +183,58 @@ uint32_t app(uint32_t param1, uint32_t param2)
//
// char *ptr = (char *)param1;
// char *pathName;
uint32_t retCode = 1;
int argc = 0;
int help_flag = 0;
int verbose_flag = 0;
int opt;
char *argv[20];
char *ptr = strtok((char *)param1, " ");
uint32_t retCode = 1;
// If the invoking command is given, add it to argv at the start.
//
if(param2 != 0)
{
argv[argc++] = (char *)param2;
}
// Now convert the parameter line into argc/argv suitable for getopt to use.
while (ptr && argc < 20-1)
{
argv[argc++] = ptr;
ptr = strtok(0, " ");
}
argv[argc] = 0;
// Define parameters to be processed.
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", 'h', OPTPARSE_NONE},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
case 'h':
help_flag = 1;
break;
case 'v':
verbose_flag = 1;
break;
case '?':
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}
// Get name of file to load.
//

View File

@@ -6,9 +6,10 @@
// Description: A TranZPUter helper utility, allowing a remote hardware reset of the tranZPUter
// board and host (not K64F).
// Credits:
// Copyright: (c) 2019-2020 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2021 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// Feb 2021 - Replaced getopt_long with optparse as it is buggy and crashes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -41,7 +42,6 @@
#include <usb_serial.h>
#include <core_pins.h>
#include <Arduino.h>
#include <getopt.h>
#include "k64f_soc.h"
#include <../../libraries/include/stdmisc.h>
#elif defined(__ZPU__)
@@ -65,6 +65,12 @@
#else
#error OS not defined, use __ZPUTA__ or __ZOS__
#endif
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include <optparse.h>
//
#include <app.h>
#include <tranzputer.h>
@@ -74,8 +80,8 @@
#include <tools.c>
// Version info.
#define VERSION "v1.0"
#define VERSION_DATE "15/05/2020"
#define VERSION "v1.1"
#define VERSION_DATE "21/02/2021"
#define APP_NAME "TZRESET"
// Simple help screen to remmber how this utility works!!
@@ -111,7 +117,6 @@ uint32_t app(uint32_t param1, uint32_t param2)
int reset_flag = 0;
int verbose_flag = 0;
int opt;
int option_index = 0;
uint8_t memoryMode = TZMM_ORIG;
long val = 0;
char *argv[20];
@@ -135,19 +140,21 @@ uint32_t app(uint32_t param1, uint32_t param2)
argv[argc] = 0;
// Define parameters to be processed.
static struct option long_options[] =
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", no_argument, 0, 'h'},
{"load", no_argument, 0, 'l'},
{"memorymode", required_argument, 0, 'm'},
{"reset", no_argument, 0, 'r'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
{"help", 'h', OPTPARSE_NONE},
{"load", 'l', OPTPARSE_NONE},
{"memorymode", 'm', OPTPARSE_REQUIRED},
{"reset", 'r', OPTPARSE_NONE},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
while((opt = getopt_long(argc, argv, ":hlm:rv", long_options, &option_index)) != -1)
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
@@ -160,9 +167,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
break;
case 'm':
if(xatoi(&argv[optind-1], &val) == 0 || val >= 0x20)
if(xatoi(&options.optarg, &val) == 0 || val >= 0x20)
{
printf("Illegal numeric:%s\n", argv[optind-1]);
printf("Illegal numeric:%s\n", options.optarg);
return(1);
}
memoryMode = (uint8_t)val;
@@ -176,12 +183,9 @@ uint32_t app(uint32_t param1, uint32_t param2)
verbose_flag = 1;
break;
case ':':
printf("Option %s needs a value\n", argv[optind-1]);
break;
case '?':
printf("Unknown option: %s, ignoring!\n", argv[optind-1]);
break;
case '?':
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}

View File

@@ -625,11 +625,16 @@ elif [ "${OS}" = "ZOS" ]; then
if [ $? != 0 ]; then
Fatal "Aborting, failed to build zOS!"
fi
cp ${BUILDPATH}/zOS/${OSBUILDSTR}.bin ${BUILDPATH}/build/SD/${OS_SD_TARGET}
# Also create a copy of the OS for use by the tranZPUter SW-700 project.
mkdir -p ${BUILDPATH}/build/SD/ZOS
cp ${BUILDPATH}/zOS/${OSBUILDSTR}.bin ${BUILDPATH}/build/SD/ZOS/ZOS.ROM
if [ "${CPUTYPE}" = "__ZPU__" ]; then
cp ${BUILDPATH}/zOS/${OSBUILDSTR}.bin ${BUILDPATH}/build/SD/${OS_SD_TARGET}
cp ${BUILDPATH}/zOS/${OSBUILDSTR}.bin ${BUILDPATH}/build/SD/ZOS/ZOS.ROM
else
cp ${BUILDPATH}/zOS/main.bin ${BUILDPATH}/build/SD/${OS_SD_TARGET}
cp ${BUILDPATH}/zOS/main.bin ${BUILDPATH}/build/SD/ZOS/ZOS.K64F.ROM
fi
fi
# Build the apps and install into the build tree.

View File

@@ -12,9 +12,11 @@ ZPU_E115_APPSIZE=0x8000
ZPU_E115_HEAPSIZE=0x4000
ZPU_E115_STACKSIZE=0x3D80
ROOT_DIR=/dvlp/Projects/dev/github/
(
# Ensure the zOS target directories exist.
cd /dvlp/Projects/dev/github/zSoft
cd ${ROOT_DIR}/zSoft
mkdir -p SD/SharpMZ
mkdir -p SD/Dev
mkdir -p SD/K64F
@@ -49,30 +51,30 @@ if [ $? != 0 ]; then
exit 1
fi
cp -r build/SD/* SD/K64F/
rsync -avh * psmart@192.168.15.205:/dvlp/Projects/dev/github/zSoft/
rsync -avh * psmart@192.168.15.205:${ROOT_DIR}/zSoft/
if [ $? != 0 ]; then
echo "Error syncing K64F Distribution..."
exit 1
fi
# Simple mechanism to prevent remote build and programming of the K64F.
diff /dvlp/Projects/dev/github/zSoft/zOS/main.bin /dvlp/Projects/dev/github/zSoft/zOS/main.bak
diff ${ROOT_DIR}/zSoft/zOS/main.bin ${ROOT_DIR}/zSoft/zOS/main.bak
if [ $? -ne 0 ]; then
echo "GO" > /dvlp/Projects/dev/github/zSoft/.dobuild
rsync -avh .dobuild psmart@192.168.15.205:/dvlp/Projects/dev/github/zSoft/
echo "GO" > ${ROOT_DIR}/zSoft/.dobuild
rsync -avh .dobuild psmart@192.168.15.205:${ROOT_DIR}/zSoft/
if [ $? != 0 ]; then
echo "Error syncing K64F Distribution..."
exit 1
fi
fi
cp /dvlp/Projects/dev/github/zSoft/zOS/main.bin /dvlp/Projects/dev/github/zSoft/zOS/main.bak
cp ${ROOT_DIR}/zSoft/zOS/main.bin ${ROOT_DIR}/zSoft/zOS/main.bak
)
if [ $? != 0 ]; then
exit 1
fi
# Ensure the TZFS target directories exist
k64fsddir=/dvlp/Projects/dev/github/zSoft/SD/K64F
tzfsdir=/dvlp/Projects/dev/github/tranZPUter/software
k64fsddir=${ROOT_DIR}/zSoft/SD/K64F
tzfsdir=${ROOT_DIR}/tranZPUter/software
mkdir -p $k64fsddir/TZFS/
mkdir -p $k64fsddir/MZF/
mkdir -p $k64fsddir/CPM/

View File

@@ -1945,9 +1945,7 @@ uint8_t mzSweepKeys(void)
// Read the scan lines.
keyboard.scanbuf[0][strobe-0xF0] = (uint8_t)(*(volatile uint32_t *)(MBADDR_8BIT_KEYPB));
// printf("%02x ", (uint8_t)*(uint32_t *)(MBADDR_8BIT_KEYPB));
}
// printf("\n");
// Now look for active keys.
for(uint8_t strobeIdx=0; strobeIdx < 10; strobeIdx++)
@@ -2191,11 +2189,9 @@ int mzServiceCall(uint8_t cmd)
// Error occurred?
if((status=mzSDGetStatus(TZSVC_TIMEOUT, TZSVC_STATUS_REQUEST)) != -1)
{
if((status=mzSDGetStatus(TZSVC_TIMEOUT, TZSVC_STATUS_PROCESSING)) == -1)
{
retries--;
}
status=mzSDGetStatus(TZSVC_TIMEOUT, TZSVC_STATUS_PROCESSING);
}
retries--;
} while(retries > 0 && (uint8_t)status != TZSVC_STATUS_OK);
return(retries == 0 ? -1 : status);
@@ -2208,7 +2204,7 @@ int mzSDServiceCall(uint8_t drive, uint8_t cmd)
{
// Locals.
int status;
// Setup control structure to request a disk sector from the I/O processor.
svcControl->fileSector = drive;

View File

@@ -44,7 +44,7 @@
// v1.4 Dec 2020 - With the advent of the tranZPUter SW-700 v1.3, major changes needed to
// to be made. Some of the overhanging code from v1.0 of the original
// tranZPUter SW had to be stripped out and direct 24bit addressing, as
// opposed to memory mode configuration was implemented. This added race
// opposed to memory mode configuration, was implemented. This added race
// states as it was now much quicker so further tweaks using direct
// register writes had to be made.
// This version see's the advent of soft CPU's in hardware and the
@@ -2070,8 +2070,6 @@ void loadTranZPUterDefaultROMS(uint8_t cpuConfig)
// Locals.
FRESULT result = 0;
printf("I have config:%02x\n", cpuConfig);
// Set CPU and hold soft CPU clock if configured.
writeZ80IO(IO_TZ_CPUCFG, cpuConfig & CPUMODE_IS_SOFT_MASK, TRANZPUTER);
@@ -2145,7 +2143,6 @@ printf("I have config:%02x\n", cpuConfig);
// If autoboot flag set, force a restart to the ROM which will call User ROM startup code.
if(osControl.tzAutoBoot)
{
printf("making reset\n");
// Set the memory model to BOOT so we can bootstrap TZFS.
resetZ80(TZMM_BOOT);
}
@@ -3646,7 +3643,7 @@ void processServiceRequest(void)
uint8_t status = 0;
uint32_t actualFreq;
uint32_t copySize = TZSVC_CMD_STRUCT_SIZE;
printf("Service request\n");
// A request requires multiple transactions on the Z80 bus, so to avoid multiple request/ack cycles, we gain access then hold it until the end of the request.
//
if(reqZ80Bus(DEFAULT_BUSREQ_TIMEOUT) == 0)
@@ -3666,7 +3663,6 @@ printf("Service request\n");
copyFromZ80((uint8_t *)&svcControl.sector, z80Control.svcControlAddr+TZSVC_CMD_SIZE, TZSVC_SECTOR_SIZE, z80Control.svcControlAddr > 0x80000 ? FPGA : TRANZPUTER);
}
printf("Cmd=%02x\n", svcControl.cmd);
// Check this is a valid request.
if(svcControl.result == TZSVC_STATUS_REQUEST)
{
@@ -3849,7 +3845,7 @@ printf("Cmd=%02x\n", svcControl.cmd);
// Switch the hardware to select the hard Z80 CPU. This involves the switch then a reset procedure.
//
case TZSVC_CMD_CPU_SETZ80:
printf("Switch to Z80\n");
//printf("Switch to Z80\n");
// Switch to hard Z80.
writeZ80IO(IO_TZ_CPUCFG, CPUMODE_SET_Z80, TRANZPUTER);
@@ -3863,7 +3859,7 @@ printf("Switch to Z80\n");
// Switch the hardware to select the soft T80 CPU. This involves the switch.
//
case TZSVC_CMD_CPU_SETT80:
printf("Switch to T80\n");
//printf("Switch to T80\n");
// Switch to soft T80 cpu.
writeZ80IO(IO_TZ_CPUCFG, CPUMODE_SET_T80, TRANZPUTER);
@@ -3874,7 +3870,7 @@ printf("Switch to T80\n");
// Switch the hardware to select the soft ZPU Evolution CPU. This involves the switch.
//
case TZSVC_CMD_CPU_SETZPUEVO:
printf("Switch to EVO\n");
//printf("Switch to EVO\n");
// Switch to soft T80 cpu.
writeZ80IO(IO_TZ_CPUCFG, CPUMODE_SET_ZPU_EVO, TRANZPUTER);
@@ -3886,7 +3882,6 @@ printf("Switch to EVO\n");
// physical initialisation.
case TZSVC_CMD_SD_DISKINIT:
// No logic needed as the K64F initialises the underlying drive and the host accesses, via a mapping table, the 2-> partitions.
printf("Disk init\n");
break;
// Raw read access to the SD card.
@@ -3949,7 +3944,6 @@ printf("Disk init\n");
{
printf("Failed to request access to the Z80 Bus, cannot service request.\n");
}
printf("Exit request\n");
return;
}

View File

@@ -39,19 +39,142 @@
extern "C" {
#endif
// Video display constants.
#define VC_MAX_ROWS 25 // Maximum number of rows on display.
#define VC_MAX_COLUMNS 80 // Maximum number of columns on display.
#define VC_MAX_BUFFER_ROWS 50 // Maximum number of backing store rows for scrollback feature.
#define VC_DISPLAY_BUFFER_SIZE VC_MAX_COLUMNS * VC_MAX_BUFFER_ROWS // Size of the display buffer for scrollback.
// Target ZPU memory map.
// ----------------------
//
// Y+080000:Y+0FFFFF = 512K Video address space - the video processor memory will be directly mapped into this space as follows:
// 0x180000 - 0x18FFFF = 64K Video / Attribute RAM
// 0x190000 - 0x19FFFF = 64K Character Generator ROM/PCG RAM.
// 0x1A0000 - 0x1BFFFF = 128K Red Framebuffer address space.
// 0x1C0000 - 0x1DFFFF = 128K Blue Framebuffer address space.
// 0x1E0000 - 0x1FFFFF = 128K Green Framebuffer address space.
// This invokes memory read/write operations but the Video Read/Write signal is directly set, MREQ is not set. This
// allows direct writes to be made to the FPGA video logic, bypassing the CPLD memory manager.
// All reads are 32bit, writes are 8, 16 or 32bit wide on word boundary.
//
// Z80 Bus Interface.
// ------------------
//
// 24bit address, 8 bit data. The Z80 Memory and I/O are mapped into linear ZPU address space. The ZPU makes standard memory transactions and this state machine holds the ZPU whilst it performs the Z80 transaction.
//
// Depending on the accessed address will determine the type of transaction. In order to provide byte level access on a 32bit read CPU, a bank of addresses, word aligned per byte is assigned in addition to
// an address to read 32bit word aligned value.
//
// Y+100000:Y+17FFFF = 512K Static RAM on the tranZPUter board. All reads are 32bit, all writes are 8, 16 or 32bit wide on word boundary.
// Y+180000:Y+1BFFFF = 64K address space on host mainboard (ie. RAM/ROM/Memory mapped I/O) accessed 1 byte at a time. The physical address is word aligned per byte, so 4 bytes on the ZPU address space = 1
// byte on the Z80 address space. ie. 0x00780 ZPU = 0x0078 Z80.
// Y+1C0000:Y+1FFFFF = 64K I/O space on the host mainboard or the underlying CPLD/FPGA. 64K address space is due to the Z80 ability to address 64K via the Accumulator being set in 15:8 and the port in 7:0.
// The ZPU, via a direct address will mimic this ability for hardware which requires it. ie. A write to 0x3F with 0x10 in the accumulator would yield an address of 0x103f.
// All reads are 8 bit, writes are 8, 16 or 32bit wide on word boundary. The physical address is word aligned per byte, so 4 bytes on the ZPU address space = 1
// byte on the Z80 address space. ie. 0x00780 ZPU = 0x0078 Z80.
//
// Y+200000:Y+20FFFF = 64K address space on host mainboard (ie. RAM/ROM/Memory mapped I/O) accessed 4 bytes at a time, a 32 bit read will return 4 consecutive bytes,1start of read must be on a 32bit word boundary.
// Y+280000:Y+2FFFFF = 512K unassigned.
//
// Y = 2Mbyte sector in ZPU address space the Z80 bus interface is located. This is normally below the ZPU I/O sector and set to 0xExxxxx
//
//
// 0x000000 00000000 - Normal Sharp MZ behaviour, Video Controller controlled by Z80 bus transactions.
// Y+100000:Y+17FFFF = 512K Static RAM on the tranZPUter board. All reads are 32bit, all writes are 8, 16 or 32bit wide on word boundary.
// Y+180000:Y+1BFFFF = 64K address space on host mainboard (ie. RAM/ROM/Memory mapped I/O) accessed 1 byte at a time. The physical address is word aligned per byte, so 4 bytes on the ZPU address space = 1
// byte on the Z80 address space. ie. 0x00780 ZPU = 0x0078 Z80.
// Y+1C0000:Y+1FFFFF = 64K I/O space on the host mainboard or the underlying CPLD/FPGA. 64K address space is due to the Z80 ability to address 64K via the Accumulator being set in 15:8 and the port in 7:0.
// The ZPU, via a direct address will mimic this ability for hardware which requires it. ie. A write to 0x3F with 0x10 in the accumulator would yield an address of 0xF103f.
// All reads are 8 bit, writes are 8, 16 or 32bit wide on word boundary. The physical address is word aligned per byte, so 4 bytes on the ZPU address space = 1
// byte on the Z80 address space. ie. 0x00780 ZPU = 0x0078 Z80.
// Y+200000:Y+20FFFF = 64K address space on host mainboard (ie. RAM/ROM/Memory mapped I/O) accessed 4 bytes at a time, a 32 bit read will return 4 consecutive bytes,1start of read must be on a 32bit word boundary.
//
// Where Y is the base address, 0xC00000 in this implementation.
// -----------------------------------------------------------------------------------------------------------------------
//
// Video direct addressing.
// ------------------------
//
// Address A23 -A16
// Y+0x080000 00001000 - Memory and I/O ports mapped into direct addressable memory location.
//
// A15 - A8 A7 - A0
// I/O registers are mapped to the bottom 256 bytes mirroring the I/O address.
// Y+0x0800D0 00000000 11010000 - 0xD0 - Set the parameter number to update.
// 00000000 11010001 - 0xD1 - Update the lower selected parameter byte.
// 00000000 11010010 - 0xD2 - Update the upper selected parameter byte.
// 00000000 11010011 - 0xD3 - set the palette slot Off position to be adjusted.
// 00000000 11010100 - 0xD4 - set the palette slot On position to be adjusted.
// 00000000 11010101 - 0xD5 - set the red palette value according to the PALETTE_PARAM_SEL address.
// 00000000 11010110 - 0xD6 - set the green palette value according to the PALETTE_PARAM_SEL address.
// Y+0x0800D7 00000000 11010111 - 0xD7 - set the blue palette value according to the PALETTE_PARAM_SEL address.
//
// Y+0x0800E0 00000000 11100000 - 0xE0 MZ80B PPI
// 00000000 11100100 - 0xE4 MZ80B PIT
// Y+0x0800E8 00000000 11101000 - 0xE8 MZ80B PIO
//
// 00000000 11110000 -
// 00000000 11110001 -
// 00000000 11110010 -
// Y+0x0800F3 00000000 11110011 - 0xF3 set the VGA border colour.
// 00000000 11110100 - 0xF4 set the MZ80B video in/out mode.
// 00000000 11110101 - 0xF5 sets the palette.
// 00000000 11110110 - 0xF6 set parameters.
// 00000000 11110111 - 0xF7 set the graphics processor unit commands.
// 00000000 11111000 - 0xF6 set parameters.
// 00000000 11111001 - 0xF7 set the graphics processor unit commands.
// 00000000 11111010 - 0xF8 set the video mode.
// 00000000 11111011 - 0xF9 set the graphics mode.
// 00000000 11111100 - 0xFA set the Red bit mask
// 00000000 11111101 - 0xFB set the Green bit mask
// 00000000 11111110 - 0xFC set the Blue bit mask
// Y+0x0800FD 00000000 11111111 - 0xFD set the Video memory page in block C000:FFFF
//
// Memory registers are mapped to the E000 region as per base machines.
// Y+0x08E010 11100000 00010010 - Program Character Generator RAM. E010 - Write cycle (Read cycle = reset memory swap).
// 11100000 00010100 - Normal display select.
// 11100000 00010101 - Inverted display select.
// 11100010 00000000 - Scroll display register. E200 - E2FF
// Y+0x08E2FF 11111111
//
// Y+0x090000 00001001 - Video/Attribute RAM. 64K Window.
// Y+0x09D000 11010000 00000000 - Video RAM
// Y+0x09D7FF 11010111 11111111
// Y+0x09D800 11011000 00000000 - Attribute RAM
// Y+0x09DFFF 11011111 11111111
//
// Y+0x0A0000 00001010 - Character Generator RAM 64K Window.
// Y+0x0A0000 00000000 00000000 - CGROM
// Y+0x0A0FFF 00001111 11111111
// Y+0x0A1000 00010000 00000000 - CGRAM
// Y+0x0A1FFF 00011111 11111111
//
// Y+0x0C0000 00001100 - 128K Red framebuffer.
// 00000000 00000000 - Red pixel addressed framebuffer. Also MZ-80B GRAM I memory in lower 8K
// Y+0x0C3FFF 00111111 11111111
// Y+0x0D0000 00001101 - 128K Blue framebuffer.
// 00000000 00000000 - Blue pixel addressed framebuffer. Also MZ-80B GRAM II memory in lower 8K
// Y+0x0D3FFF 00111111 11111111
// Y+0x0E0000 00001110 - 128K Green framebuffer.
// 00000000 00000000 - Green pixel addressed framebuffer.
// Y+0x0E3FFF 00111111 11111111
//
// Base addresses and sizes within the FPGA/Video Controller.
#define VIDEO_BASE_ADDR 0xC80000
#define Z80_BUS_BASE_ADDR 0xD00000
#define VIDEO_VRAM_BASE_ADDR Z80_BUS_BASE_ADDR + 0x18D000 // Base address of the character video RAM using direct addressing.
#define VIDEO_VRAM_BASE_ADDR VIDEO_BASE_ADDR + 0x01D000 // Base address of the character video RAM using direct addressing.
#define VIDEO_VRAM_SIZE 0x800 // Size of the video RAM.
#define VIDEO_ARAM_BASE_ADDR Z80_BUS_BASE_ADDR + 0x18D800 // Base address of the character attribute RAM using direct addressing.
#define VIDEO_ARAM_BASE_ADDR VIDEO_BASE_ADDR + 0x01D800 // Base address of the character attribute RAM using direct addressing.
#define VIDEO_ARAM_SIZE 0x800 // Size of the attribute RAM.
#define VIDEO_IO_BASE_ADDR Z80_BUS_BASE_ADDR + 0x190000
#define VIDEO_IO_BASE_ADDR VIDEO_BASE_ADDR + 0x000000
// Memory addresses of I/O and Memory mapped I/O in the Video Controller which are mapped to direct memory accessed addresses.
//
#define VC_8BIT_BASE_ADDR Z80_BUS_BASE_ADDR + 0x130000
#define VC_32BIT_BASE_ADDR Z80_BUS_BASE_ADDR + 0x140000
// 8 Bit access addresses - used for writing, read can only be on a 32bit boundary with lower address lines set to 00. Writing can write upto 4 consecutive addresses.
#define VC_8BIT_BASE_ADDR VIDEO_BASE_ADDR + 0x000000
#define VC_32BIT_BASE_ADDR VIDEO_BASE_ADDR + 0x000000
// 8 Bit access addresses - used for writing, read can only be on a 32bit boundary with lower address lines set to 00. Writing can write upto 4 consecutive addresses if desired.
#define VCADDR_8BIT_PALSLCTOFF VC_8BIT_BASE_ADDR + 0xD3 // Set the palette slot Off position to be adjusted.
#define VCADDR_8BIT_PALSLCTON VC_8BIT_BASE_ADDR + 0xD4 // Set the palette slot On position to be adjusted.
#define VCADDR_8BIT_PALSETRED VC_8BIT_BASE_ADDR + 0xD5 // Set the red palette value according to the PALETTE_PARAM_SEL address.
@@ -96,7 +219,7 @@
#define VCADDR_8BIT_SCLDSP VC_8BIT_BASE_ADDR + 0xE200 // Hardware scroll, a read to each location adds 8 to the start of the video access address therefore creating hardware scroll. 00 - reset to power up
#define VCADDR_8BIT_SCLBASE VC_8BIT_BASE_ADDR + 0xE2 // High byte scroll base.
// 32 Bit access addresses - used for reading and writing, read and write can only be 1 byte to 1 address.
// 32 Bit access addresses for 8bit registers - used for reading, address is shifted right by 2 and the resulting byte read into bits 7:0, 31:8 are zero.
#define VCADDR_32BIT_PALSLCTOFF VC_32BIT_BASE_ADDR + (4*0xD3) // Set the palette slot Off position to be adjusted.
#define VCADDR_32BIT_PALSLCTON VC_32BIT_BASE_ADDR + (4*0xD4) // Set the palette slot On position to be adjusted.
#define VCADDR_32BIT_PALSETRED VC_32BIT_BASE_ADDR + (4*0xD5) // Set the red palette value according to the PALETTE_PARAM_SEL address.
@@ -142,12 +265,7 @@
#define VCADDR_32BIT_SCLDSP VC_32BIT_BASE_ADDR + (4*0xE200) // Hardware scroll, a read to each location adds 8 to the start of the video access address therefore creating hardware scroll. 00 - reset to power up
#define VCADDR_32BIT_SCLBASE VC_32BIT_BASE_ADDR + (4*0xE2) // High byte scroll base.
#define VC_MAX_ROWS 25 // Maximum number of rows on display.
#define VC_MAX_COLUMNS 80 // Maximum number of columns on display.
#define VC_MAX_BUFFER_ROWS 50 // Maximum number of backing store rows for scrollback feature.
#define VC_DISPLAY_BUFFER_SIZE VC_MAX_COLUMNS * VC_MAX_BUFFER_ROWS // Size of the display buffer for scrollback.
// Memory mapped I/O on the mainboard.
// Memory mapped I/O on the mainboard. These addresses are processed by the Z80BUS FSM which converts a 32bit ZPU cycle into several 8bi Z80 cycles.
//
#define MB_8BIT_BASE_ADDR Z80_BUS_BASE_ADDR + 0x080000
#define MB_32BIT_BASE_ADDR Z80_BUS_BASE_ADDR + 0x100000
@@ -239,90 +357,6 @@
// Y+000000:Y+07FFFF = 512K Static RAM on the tranZPUter board. All reads are 32bit, all writes are 8, 16 or 32bit wide on word boundary.
// Y+080000:Y+0BFFFF = 64K address space on host mainboard (ie. RAM/ROM/Memory mapped I/O) accessed 1 byte at a time. The physical address is word aligned per byte, so 4 bytes on the ZPU address space = 1
// byte on the Z80 address space. ie. 0x00780 ZPU = 0x0078 Z80.
// Y+0C0000:Y+0FFFFF = 64K I/O space on the host mainboard or the underlying CPLD/FPGA. 64K address space is due to the Z80 ability to address 64K via the Accumulator being set in 15:8 and the port in 7:0.
// The ZPU, via a direct address will mimic this ability for hardware which requires it. ie. A write to 0x3F with 0x10 in the accumulator would yield an address of 0xF103f.
// All reads are 8 bit, writes are 8, 16 or 32bit wide on word boundary. The physical address is word aligned per byte, so 4 bytes on the ZPU address space = 1
// byte on the Z80 address space. ie. 0x00780 ZPU = 0x0078 Z80.
//
// Y+100000:Y+10FFFF = 64K address space on host mainboard (ie. RAM/ROM/Memory mapped I/O) accessed 4 bytes at a time, a 32 bit read will return 4 consecutive bytes,1start of read must be on a 32bit word boundary.
// Y+180000:Y+1FFFFF = 512 Video address space - the video processor memory will be directly mapped into this space as follows:
// 0x180000 - 0x18FFFF = 64K Video / Attribute RAM
// 0x190000 - 0x19FFFF = 64K Character Generator ROM/PCG RAM.
// 0x1A0000 - 0x1BFFFF = 128K Red Framebuffer address space.
// 0x1C0000 - 0x1DFFFF = 128K Blue Framebuffer address space.
// 0x1E0000 - 0x1FFFFF = 128K Green Framebuffer address space.
// This invokes memory read/write operations but the Video Read/Write signal is directly set, MREQ is not set. This
// allows direct writes to be made to the FPGA video logic, bypassing the CPLD memory manager.
// All reads are 32bit, writes are 8, 16 or 32bit wide on word boundary.
//
// 00000000 - Normal Sharp MZ behaviour
// 00001000 - Memory and I/O ports mapped into direct addressable memory location.
//
// A15 - A8 A7 - A0
// I/O registers are mapped to the bottom 256 bytes mirroring the I/O address.
// 00000000 11010000 - 0xD0 - Set the parameter number to update.
// 00000000 11010001 - 0xD1 - Update the lower selected parameter byte.
// 00000000 11010010 - 0xD2 - Update the upper selected parameter byte.
// 00000000 11010011 - 0xD3 - set the palette slot Off position to be adjusted.
// 00000000 11010100 - 0xD4 - set the palette slot On position to be adjusted.
// 00000000 11010101 - 0xD5 - set the red palette value according to the PALETTE_PARAM_SEL address.
// 00000000 11010110 - 0xD6 - set the green palette value according to the PALETTE_PARAM_SEL address.
// 00000000 11010111 - 0xD7 - set the blue palette value according to the PALETTE_PARAM_SEL address.
//
// 00000000 11100000 - 0xE0 MZ80B PPI
// 00000000 11100001 - 0xE4 MZ80B PIT
// 00000000 11100010 - 0xE0 MZ80B PIO
//
// 00000000 11110000 -
// 00000000 11110001 -
// 00000000 11110010 -
// 00000000 11110011 - 0xF3 set the VGA border colour.
// 00000000 11110100 - 0xF4 set the MZ80B video in/out mode.
// 00000000 11110101 - 0xF5 sets the palette.
// 00000000 11110110 - 0xF6 set parameters.
// 00000000 11110111 - 0xF7 set the graphics processor unit commands.
// 00000000 11111000 - 0xF6 set parameters.
// 00000000 11111001 - 0xF7 set the graphics processor unit commands.
// 00000000 11111010 - 0xF8 set the video mode.
// 00000000 11111011 - 0xF9 set the graphics mode.
// 00000000 11111100 - 0xFA set the Red bit mask
// 00000000 11111101 - 0xFB set the Green bit mask
// 00000000 11111110 - 0xFC set the Blue bit mask
// 00000000 11111111 - 0xFD set the Video memory page in block C000:FFFF
//
// Memory registers are mapped to the E000 region as per base machines.
// 11100000 00010010 - Program Character Generator RAM. E010 - Write cycle (Read cycle = reset memory swap).
// 11100000 00010100 - Normal display select.
// 11100000 00010101 - Inverted display select.
// 11100010 00000000 - Scroll display register. E200 - E2FF
// 11111111
//
// 00001001 - Video/Attribute RAM. 64K Window.
// 11010000 00000000 - Video RAM
// 11010111 11111111
// 11011000 00000000 - Attribute RAM
// 11011111 11111111
//
// 00001010 - Character Generator RAM
// 00000000 00000000 - CGROM
// 00001111 11111111
// 00010000 00000000 - CGRAM
// 00011111 11111111
//
// 00001100 - Red framebuffer.
// 00000000 00000000 - Red pixel addressed framebuffer. Also MZ-80B GRAM I memory in lower 8K
// 00111111 11111111
// 00001101 - Blue framebuffer.
// 00000000 00000000 - Blue pixel addressed framebuffer. Also MZ-80B GRAM II memory in lower 8K
// 00111111 11111111
// 00001110 - Green framebuffer.
// 00000000 00000000 - Green pixel addressed framebuffer.
// 00111111 11111111
//
// tranZPUter Memory Modes - select one of the 32 possible memory models using these constants.
//
#define TZMM_ORIG 0x00 // Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
@@ -647,7 +681,6 @@
// Convert big endiam to little endian.
#define convBigToLittleEndian(num) ((num>>24)&0xff) | ((num<<8)&0xff0000) | ((num>>8)&0xff00) | ((num<<24)&0xff000000)
// Possible machines the tranZPUter can be hosted on and can emulate.
//
enum MACHINE_TYPES {
@@ -741,7 +774,6 @@ typedef struct __attribute__((__packed__)) {
};
} t_dirMap;
// Structure to maintain all MZ700 hardware control information in order to emulate the machine.
//
typedef struct {
@@ -982,8 +1014,6 @@ uint8_t mzSDRead(uint8_t, uint32_t, uint32_t);
uint8_t mzSDWrite(uint8_t, uint32_t, uint32_t);
void testRoutine(void);
// Getter/Setter methods!
#ifdef __cplusplus

View File

@@ -7,7 +7,7 @@
// A set of tools to be used by the zOS application.
//
// Credits:
// Copyright: (c) 2019 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-21 Philip Smart <philip.smart@net2net.org>
//
// History: January 2019 - Initial script written.
//
@@ -112,6 +112,7 @@ extern "C" {
#define CMD_TZ_CLK 154 // tranZPUter secondary frequency set tool.
#define CMD_TZ_RESET 155 // tranZPUter memory reset tool.
#define CMD_TZ_IO 156 // tranZPUter memory IO read/write tool.
#define CMD_TZ_FLUPD 157 // tranZPUter K64F FlashRAM update tool.
#define CMD_BADKEY -1
#define CMD_NOKEY 0
#define CMD_GROUP_DISK 1
@@ -411,6 +412,7 @@ static t_cmdstruct cmdTable[] = {
{ "tzclk", BUILTIN_DEFAULT, CMD_TZ_CLK, CMD_GROUP_TZ },
{ "tzreset", BUILTIN_DEFAULT, CMD_TZ_RESET, CMD_GROUP_TZ },
{ "tzio", BUILTIN_DEFAULT, CMD_TZ_IO, CMD_GROUP_TZ },
{ "tzflupd", BUILTIN_DEFAULT, CMD_TZ_FLUPD, CMD_GROUP_TZ },
#endif
};
#endif
@@ -529,6 +531,7 @@ static t_helpstruct helpTable[] = {
{ CMD_TZ_CLK, "--help", "CPU Freq set tool" },
{ CMD_TZ_RESET, "--help", "Remote reset tool" },
{ CMD_TZ_IO, "--help", "I/O read/write tool" },
{ CMD_TZ_FLUPD, "--help", "Update K64F FlashRAM" },
#endif
};
#endif

View File

@@ -633,7 +633,7 @@ typedef struct {
// Structure to maintain all the control and management variables of the Z80 and underlying hardware so that the state of run is well known by any called method.
//
typedef struct {
#ifndef __APP__
#if !defined(__APP__) || defined(__TZFLUPD__)
uint32_t svcControlAddr; // Address of the service control record within the 512K static RAM bank.
uint8_t refreshAddr; // Refresh address for times when the K64F must issue refresh cycles on the Z80 bus.
uint8_t disableRefresh; // Disable refresh if the mainboard DRAM isnt being used.

View File

@@ -354,9 +354,9 @@ typedef volatile unsigned int* register_t;
#define SOCCFG_BASE IO_ADDR_PERIPHERALS + 0xF00
// Registers
#define SOCCFG_ZPU_ID 0x00 // ID of the instantiated ZPU
#define SOCCFG_SYSFREQ 0x04 // System Clock Frequency in MHz x 10 (ie. 100KHź)
#define SOCCFG_MEMFREQ 0x08 // Sysbus SDRAM Clock Frequency in MHz x 10 (ie. 100KHź)
#define SOCCFG_WBMEMFREQ 0x0c // Wishbone SDRAM Clock Frequency in MHz x 10 (ie. 100KHź)
#define SOCCFG_SYSFREQ 0x04 // System Clock Frequency in MHz x 10 (ie. 100MHz = 1000)
#define SOCCFG_MEMFREQ 0x08 // Sysbus SDRAM Clock Frequency in MHz x 10 (ie. 100MHz = 1000)
#define SOCCFG_WBMEMFREQ 0x0c // Wishbone SDRAM Clock Frequency in MHz x 10 (ie. 100MHz = 1000)
#define SOCCFG_DEVIMPL 0x10 // Bit map of devices implemented in SOC.
#define SOCCFG_BRAMADDR 0x14 // Address of Block RAM.
#define SOCCFG_BRAMSIZE 0x18 // Size of Block RAM.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,403 @@
/* Optparse --- portable, reentrant, embeddable, getopt-like option parser
*
* This is free and unencumbered software released into the public domain.
*
* To get the implementation, define OPTPARSE_IMPLEMENTATION.
* Optionally define OPTPARSE_API to control the API's visibility
* and/or linkage (static, __attribute__, __declspec).
*
* The POSIX getopt() option parser has three fatal flaws. These flaws
* are solved by Optparse.
*
* 1) Parser state is stored entirely in global variables, some of
* which are static and inaccessible. This means only one thread can
* use getopt(). It also means it's not possible to recursively parse
* nested sub-arguments while in the middle of argument parsing.
* Optparse fixes this by storing all state on a local struct.
*
* 2) The POSIX standard provides no way to properly reset the parser.
* This means for portable code that getopt() is only good for one
* run, over one argv with one option string. It also means subcommand
* options cannot be processed with getopt(). Most implementations
* provide a method to reset the parser, but it's not portable.
* Optparse provides an optparse_arg() function for stepping over
* subcommands and continuing parsing of options with another option
* string. The Optparse struct itself can be passed around to
* subcommand handlers for additional subcommand option parsing. A
* full reset can be achieved by with an additional optparse_init().
*
* 3) Error messages are printed to stderr. This can be disabled with
* opterr, but the messages themselves are still inaccessible.
* Optparse solves this by writing an error message in its errmsg
* field. The downside to Optparse is that this error message will
* always be in English rather than the current locale.
*
* Optparse should be familiar with anyone accustomed to getopt(), and
* it could be a nearly drop-in replacement. The option string is the
* same and the fields have the same names as the getopt() global
* variables (optarg, optind, optopt).
*
* Optparse also supports GNU-style long options with optparse_long().
* The interface is slightly different and simpler than getopt_long().
*
* By default, argv is permuted as it is parsed, moving non-option
* arguments to the end. This can be disabled by setting the `permute`
* field to 0 after initialization.
*/
#ifndef OPTPARSE_H
#define OPTPARSE_H
#ifndef OPTPARSE_API
# define OPTPARSE_API
#endif
struct optparse {
char **argv;
int permute;
int optind;
int optopt;
char *optarg;
char errmsg[64];
int subopt;
};
enum optparse_argtype {
OPTPARSE_NONE,
OPTPARSE_REQUIRED,
OPTPARSE_OPTIONAL
};
struct optparse_long {
const char *longname;
int shortname;
enum optparse_argtype argtype;
};
/**
* Initializes the parser state.
*/
OPTPARSE_API
void optparse_init(struct optparse *options, char **argv);
/**
* Read the next option in the argv array.
* @param optstring a getopt()-formatted option string.
* @return the next option character, -1 for done, or '?' for error
*
* Just like getopt(), a character followed by no colons means no
* argument. One colon means the option has a required argument. Two
* colons means the option takes an optional argument.
*/
OPTPARSE_API
int optparse(struct optparse *options, const char *optstring);
/**
* Handles GNU-style long options in addition to getopt() options.
* This works a lot like GNU's getopt_long(). The last option in
* longopts must be all zeros, marking the end of the array. The
* longindex argument may be NULL.
*/
OPTPARSE_API
int optparse_long(struct optparse *options,
const struct optparse_long *longopts,
int *longindex);
/**
* Used for stepping over non-option arguments.
* @return the next non-option argument, or NULL for no more arguments
*
* Argument parsing can continue with optparse() after using this
* function. That would be used to parse the options for the
* subcommand returned by optparse_arg(). This function allows you to
* ignore the value of optind.
*/
OPTPARSE_API
char *optparse_arg(struct optparse *options);
/* Implementation */
#ifdef OPTPARSE_IMPLEMENTATION
#define OPTPARSE_MSG_INVALID "invalid option"
#define OPTPARSE_MSG_MISSING "option requires an argument"
#define OPTPARSE_MSG_TOOMANY "option takes no arguments"
static int
optparse_error(struct optparse *options, const char *msg, const char *data)
{
unsigned p = 0;
const char *sep = " -- '";
while (*msg)
options->errmsg[p++] = *msg++;
while (*sep)
options->errmsg[p++] = *sep++;
while (p < sizeof(options->errmsg) - 2 && *data)
options->errmsg[p++] = *data++;
options->errmsg[p++] = '\'';
options->errmsg[p++] = '\0';
return '?';
}
OPTPARSE_API
void
optparse_init(struct optparse *options, char **argv)
{
options->argv = argv;
options->permute = 1;
options->optind = 1;
options->subopt = 0;
options->optarg = 0;
options->errmsg[0] = '\0';
}
static int
optparse_is_dashdash(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
}
static int
optparse_is_shortopt(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
}
static int
optparse_is_longopt(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
}
static void
optparse_permute(struct optparse *options, int index)
{
char *nonoption = options->argv[index];
int i;
for (i = index; i < options->optind - 1; i++)
options->argv[i] = options->argv[i + 1];
options->argv[options->optind - 1] = nonoption;
}
static int
optparse_argtype(const char *optstring, char c)
{
int count = OPTPARSE_NONE;
if (c == ':')
return -1;
for (; *optstring && c != *optstring; optstring++);
if (!*optstring)
return -1;
if (optstring[1] == ':')
count += optstring[2] == ':' ? 2 : 1;
return count;
}
OPTPARSE_API
int
optparse(struct optparse *options, const char *optstring)
{
int type;
char *next;
char *option = options->argv[options->optind];
options->errmsg[0] = '\0';
options->optopt = 0;
options->optarg = 0;
if (option == 0) {
return -1;
} else if (optparse_is_dashdash(option)) {
options->optind++; /* consume "--" */
return -1;
} else if (!optparse_is_shortopt(option)) {
if (options->permute) {
int index = options->optind++;
int r = optparse(options, optstring);
optparse_permute(options, index);
options->optind--;
return r;
} else {
return -1;
}
}
option += options->subopt + 1;
options->optopt = option[0];
type = optparse_argtype(optstring, option[0]);
next = options->argv[options->optind + 1];
switch (type) {
case -1: {
char str[2] = {0, 0};
str[0] = option[0];
options->optind++;
return optparse_error(options, OPTPARSE_MSG_INVALID, str);
}
case OPTPARSE_NONE:
if (option[1]) {
options->subopt++;
} else {
options->subopt = 0;
options->optind++;
}
return option[0];
case OPTPARSE_REQUIRED:
options->subopt = 0;
options->optind++;
if (option[1]) {
options->optarg = option + 1;
} else if (next != 0) {
options->optarg = next;
options->optind++;
} else {
char str[2] = {0, 0};
str[0] = option[0];
options->optarg = 0;
return optparse_error(options, OPTPARSE_MSG_MISSING, str);
}
return option[0];
case OPTPARSE_OPTIONAL:
options->subopt = 0;
options->optind++;
if (option[1])
options->optarg = option + 1;
else
options->optarg = 0;
return option[0];
}
return 0;
}
OPTPARSE_API
char *
optparse_arg(struct optparse *options)
{
char *option = options->argv[options->optind];
options->subopt = 0;
if (option != 0)
options->optind++;
return option;
}
static int
optparse_longopts_end(const struct optparse_long *longopts, int i)
{
return !longopts[i].longname && !longopts[i].shortname;
}
static void
optparse_from_long(const struct optparse_long *longopts, char *optstring)
{
char *p = optstring;
int i;
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
if (longopts[i].shortname && longopts[i].shortname < 127) {
int a;
*p++ = longopts[i].shortname;
for (a = 0; a < (int)longopts[i].argtype; a++)
*p++ = ':';
}
}
*p = '\0';
}
/* Unlike strcmp(), handles options containing "=". */
static int
optparse_longopts_match(const char *longname, const char *option)
{
const char *a = option, *n = longname;
if (longname == 0)
return 0;
for (; *a && *n && *a != '='; a++, n++)
if (*a != *n)
return 0;
return *n == '\0' && (*a == '\0' || *a == '=');
}
/* Return the part after "=", or NULL. */
static char *
optparse_longopts_arg(char *option)
{
for (; *option && *option != '='; option++);
if (*option == '=')
return option + 1;
else
return 0;
}
static int
optparse_long_fallback(struct optparse *options,
const struct optparse_long *longopts,
int *longindex)
{
int result;
char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
optparse_from_long(longopts, optstring);
result = optparse(options, optstring);
if (longindex != 0) {
*longindex = -1;
if (result != -1) {
int i;
for (i = 0; !optparse_longopts_end(longopts, i); i++)
if (longopts[i].shortname == options->optopt)
*longindex = i;
}
}
return result;
}
OPTPARSE_API
int
optparse_long(struct optparse *options,
const struct optparse_long *longopts,
int *longindex)
{
int i;
char *option = options->argv[options->optind];
if (option == 0) {
return -1;
} else if (optparse_is_dashdash(option)) {
options->optind++; /* consume "--" */
return -1;
} else if (optparse_is_shortopt(option)) {
return optparse_long_fallback(options, longopts, longindex);
} else if (!optparse_is_longopt(option)) {
if (options->permute) {
int index = options->optind++;
int r = optparse_long(options, longopts, longindex);
optparse_permute(options, index);
options->optind--;
return r;
} else {
return -1;
}
}
/* Parse as long option. */
options->errmsg[0] = '\0';
options->optopt = 0;
options->optarg = 0;
option += 2; /* skip "--" */
options->optind++;
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
const char *name = longopts[i].longname;
if (optparse_longopts_match(name, option)) {
char *arg;
if (longindex)
*longindex = i;
options->optopt = longopts[i].shortname;
arg = optparse_longopts_arg(option);
if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
return optparse_error(options, OPTPARSE_MSG_TOOMANY, name);
} if (arg != 0) {
options->optarg = arg;
} else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
options->optarg = options->argv[options->optind];
if (options->optarg == 0)
return optparse_error(options, OPTPARSE_MSG_MISSING, name);
else
options->optind++;
}
return options->optopt;
}
}
return optparse_error(options, OPTPARSE_MSG_INVALID, option);
}
#endif /* OPTPARSE_IMPLEMENTATION */
#endif /* OPTPARSE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,380 @@
########################################################################################################
#
# Name: app_k64f_hwctl_crt0.h
# Created: Feb 2021
# Author(s): Philip Smart
# Description: ZPUTA/zOS application startup code.
# This is the assembler startup file of an APPlication for ZPUTA and zOS programs. It
# differs from the standard APP startup file in that it removes hooks to the kernel for
# tranZPUter hardware methods so requiring direct linkage of these methods at link time.
#
# Credits:
# Copyright: (c) 2019-21 Philip Smart <philip.smart@net2net.org>
#
# History: Feb 2021 - Initial script based on zpu appcrt0.s.
#
########################################################################################################
# This source file is free software: you can redistribute it and#or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This source file is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http:#www.gnu.org;licenses;>.
########################################################################################################
.file "app_k64f_hwctl_crt0.s"
.include "k64f_macros.s"
.syntax unified
.arch armv7-m
.thumb
.section .text,"ax"
.type _start, function
// Define symbols in C to be linked against this assembly startup code.
.extern __bss_section_begin__
.extern __bss_section_end__
.extern __data_section_begin__
.extern __data_section_end__
.extern __text_section_begin__
.extern __text_section_end__
.extern app // Main app entry point.
.extern G // Global shared variables with OS.
.extern cfgSoC // Configuration structure to define CPU and hardware.
.extern stdin // Standard input file stream.
.extern stdout // Standard output file stream.
.extern stderr // Standard error file stream.
.global _start
// Save registers normally preserved in a C call.
_start: stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
stmdb sp!, {r0, r1, r2, r3};
// Copy initialized data from text area to working RAM (data) area.
ldr r1, DATA_BEGIN
ldr r2, TEXT_END
ldr r3, DATA_END
subs r3, r3, r1 // Length of initialized data
beq zerobss // Skip if none
copydata: ldrb r4, [r2], #1 // Read byte from flash
strb r4, [r1], #1 // Store byte to RAM
subs r3, r3, #1 // Decrement counter
bgt copydata // Repeat until done
// Zero uninitialized data (bss)
ldr r1, BSS_BEGIN
ldr r3, BSS_END
subs r3, r3, r1 // Length of uninitialized data
beq exec_app // Skip if none
zerobss: mov r2, #0x00 // Initialise with 0
clearbss: strb r2, [r1], #1 // Store zero
subs r3, r3, #1 // Decrement counter
bgt clearbss // Repeat until done
// Reminder, ARM calling convention in C allocation table.
//
// Register Synonym Contents? Purpose
// r0 N argument/results
// r1 N argument/results
// r2 N argument/results
// r3 N argument/results
// r4 Y local variable
// r5 Y local variable
// r6 Y local variable
// r7 Y local variable
// r8 Y local variable
// r9 Y depends on platform standard
// r10 Y local variable
// r11 fp Y frame pointer/local variable
// r12 ip N intra-procedure-call scratch
// r13 sp Y stack pointer
// r14 lr N link register
// r15 pc N program counter
// 4-> parameters are passed on the stack starting at sp. If values are pushed prior to accessing the parameters, they need to be read at the correct stack
// offset. ie. In this routine, 12 registers are pushed, 48 bytes in total, so any access to parameter 4 (first parameter on stack) is at #48.
//
// NB: To force a hard fault to see stack trace, issue instruction .word 0xffffffff inline.
// Call app(uint32_t param1, uint32_t param2)
exec_app: ldr.w r6, [sp, #48] // Get stdin, stdout, stderr file descriptors passed on stack.
ldr r4, =stdin // Setup the pointer for stdin in the app to stdin in zOS/ZPUTA.
str r6, [r4]
ldr.w r6, [sp, #52]
ldr r4, =stdout // Setup the pointer for stdout in the app to stdout in zOS/ZPUTA.
str r6, [r4]
ldr.w r6, [sp, #56]
ldr r4, =stderr // Setup the pointer for stderr in the app to stderr in zOS/ZPUTA.
str r6, [r4]
// Setup the G and cfgSoC variables using passed parameters.
ldmia.w sp!, {r0, r1, r2, r3} // Get back the parameters ready to pass to app()
ldr r4, =G // Setup the pointer for G in the app to G in zOS/ZPUTA.
str r2, [r4]
ldr r4, =cfgSoC // Setup the pointer for cfgSoC in the app to cfgSoC in zOS/ZPUTA.
str r3, [r4]
// r0 = param1, r1 = param2
bl app // Call the application.
// r0 = return code.
// Restore C call registers, load lr straight to PC, R0 = return code.
ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc}
fail_loop: b fail_loop // The pop pc above should never fail, just in case the stack gets corrupted, stay in a loop for safety.
#
#// These are filled in by the linker
#
TEXT_BEGIN: .word __text_section_begin__
TEXT_END: .word __text_section_end__
DATA_BEGIN: .word __data_section_begin__
DATA_END: .word __data_section_end__
BSS_BEGIN: .word __bss_section_begin__
BSS_END: .word __bss_section_end__
#-----------------------------------------------
# zOS/ZPUTA API Function Entry Points
#-----------------------------------------------
#
# Entry points in the parent program, zOS/ZPUTA, where the relevvant named functions can be accessed. The
# entry point in this table is used as the address for the specified function in the APPlication such that
# a call to a library function in the APPlication is actually using code in zOS/ZPUTA at runtime thus minimising
# code in the APPlication.
#
# This table doesnt consume space, just defines the addresses which will be called for the relevant function.
#
.equ funcNext, 0x04;
.equ funcAddr, OS_BASEADDR+0x420;
defapifunc break funcAddr
#
# putc and xprint calls.
#
.equ funcAddr, funcAddr+funcNext;
defapifunc putchar funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc putc funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc fputc funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc puts funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc gets funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc fgets funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc fputs funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc xatoi funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc uxatoi funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc printf funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc sprintf funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc fprintf funcAddr
#
# getc calls
#
.equ funcAddr, funcAddr+funcNext;
defapifunc getScreenWidth funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc getKey funcAddr
#
# Util calls
#
#.equ funcAddr, funcAddr+funcNext;
#defapifunc crc32_init funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc crc32_addword funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc get_dword funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc rtcSet funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc rtcGet funcAddr
#
# FatFS System Calls - For certain applications, such as the Flash RAM updater, the FatFS is embedded as the
# kernel is overwritten, so these function definitions are commented out.
#
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_open funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_close funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_read funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_write funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_lseek funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_truncate funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_sync funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_opendir funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_closedir funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_readdir funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_findfirst funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_findnext funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_mkdir funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_unlink funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_rename funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_stat funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_chmod funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_utime funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_chdir funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_chdrive funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_getcwd funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_getfree funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_getlabel funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_setlabel funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_forward funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_expand funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_mount funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_mkfs funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_fdisk funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_setcp funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_putc funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_puts funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc f_printf funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc f_gets funcAddr
#
# Low level disk calls.
#
.equ funcAddr, funcAddr+funcNext;
#defapifunc disk_read funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc disk_write funcAddr
.equ funcAddr, funcAddr+funcNext;
#defapifunc disk_ioctl funcAddr
#
# Miscellaneous calls.
#
.equ funcAddr, funcAddr+funcNext;
defapifunc getStrParam funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc getUintParam funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc set_serial_output funcAddr
#.equ funcAddr, funcAddr+funcNext;
#defapifunc printBytesPerSec funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc printFSCode funcAddr
# Memory management calls.
.equ funcAddr, funcAddr+funcNext;
defapifunc sys_malloc funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc sys_realloc funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc sys_calloc funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc sys_free funcAddr
# tranZPUter kernel methods.
.equ funcAddr, funcAddr+funcNext;
defapifunc setupZ80Pins funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc resetZ80 funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc reqZ80Bus funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc reqMainboardBus funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc reqTranZPUterBus funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc setupSignalsForZ80Access funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc releaseZ80 funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc writeZ80Memory funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc readZ80Memory funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc writeZ80IO funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc readZ80IO funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc refreshZ80 funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc refreshZ80AllRows funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc setCtrlLatch funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc setZ80CPUFrequency funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc copyFromZ80 funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc copyToZ80 funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc fillZ80Memory funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc captureVideoFrame funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc refreshVideoFrame funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc loadVideoFrameBuffer funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc saveVideoFrameBuffer funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc getVideoFrame funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc getAttributeFrame funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc loadZ80Memory funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc loadMZFZ80Memory funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc saveZ80Memory funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc memoryDumpZ80 funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc isZ80Reset funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc isZ80MemorySwapped funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc getZ80IO funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc clearZ80Reset funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc hardResetTranZPUter funcAddr
.equ funcAddr, funcAddr+funcNext;
defapifunc convertSharpFilenameToAscii funcAddr
.end

View File

@@ -106,8 +106,8 @@
#endif
// Version info.
#define VERSION "v1.1d"
#define VERSION_DATE "11/12/2020"
#define VERSION "v1.1e"
#define VERSION_DATE "04/02/2021"
#define PROGRAM_NAME "zOS"
// Utility functions.