From fbd691a5f51aa6dde4745afec430d7b77604579a Mon Sep 17 00:00:00 2001 From: Philip Smart Date: Sat, 15 May 2021 19:56:18 +0100 Subject: [PATCH] Added testing method and app for tranZPUter memory testing. --- apps/Makefile | 2 +- apps/tzmtest/Makefile | 85 ++++++++ apps/tzmtest/tzmtest.c | 338 ++++++++++++++++++++++++++++++ apps/tzmtest/tzmtest.h | 50 +++++ common/tranzputer.c | 295 +++++++++++++++++++++++++- include/tools.h | 8 +- include/tranzputer.h | 1 + libraries/lib/libimath2-k64f.a | Bin 15012 -> 15012 bytes libraries/lib/libimath2-zpu.a | Bin 5072 -> 5072 bytes libraries/lib/libumansi-k64f.a | Bin 126938 -> 126938 bytes libraries/lib/libumansi-zpu.a | Bin 51150 -> 51150 bytes libraries/lib/libummath-k64f.a | Bin 2660 -> 2660 bytes libraries/lib/libummath-zpu.a | Bin 1352 -> 1352 bytes libraries/lib/libummathf-k64f.a | Bin 64036 -> 64036 bytes libraries/lib/libummathf-zpu.a | Bin 39292 -> 39292 bytes libraries/lib/libummisc-k64f.a | Bin 6222 -> 6222 bytes libraries/lib/libummisc-zpu.a | Bin 3374 -> 3374 bytes libraries/lib/libumstdio-k64f.a | Bin 80050 -> 80050 bytes libraries/lib/libumstdio-zpu.a | Bin 32528 -> 32528 bytes rtl/IOCP_zOS_BootROM.vhd | 4 +- rtl/TZSW_DualPort3264BootBRAM.vhd | 4 +- rtl/TZSW_DualPortBootBRAM.vhd | 4 +- rtl/TZSW_SinglePortBootBRAM.vhd | 4 +- rtl/zOS_BootROM.vhd | 4 +- rtl/zOS_DualPort3264BootBRAM.vhd | 4 +- rtl/zOS_DualPortBootBRAM.vhd | 4 +- rtl/zOS_SinglePortBootBRAM.vhd | 4 +- startup/app_k64f_crt0.s | 2 + startup/app_k64f_hwctl_crt0.s | 2 + startup/mk20dx128.c | 1 + zOS/src/zOS.cpp | 4 +- 31 files changed, 798 insertions(+), 22 deletions(-) create mode 100755 apps/tzmtest/Makefile create mode 100755 apps/tzmtest/tzmtest.c create mode 100755 apps/tzmtest/tzmtest.h diff --git a/apps/Makefile b/apps/Makefile index 85c6b11..811155f 100755 --- a/apps/Makefile +++ b/apps/Makefile @@ -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 tzflupd + TZPU_SUBDIRS := tzpu tzload tzdump tzclear tzclk tzreset tzio tzflupd tzmtest endif else TZPU_SUBDIRS := diff --git a/apps/tzmtest/Makefile b/apps/tzmtest/Makefile new file mode 100755 index 0000000..ea071b7 --- /dev/null +++ b/apps/tzmtest/Makefile @@ -0,0 +1,85 @@ +######################################################################################################### +## +## 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-20 Philip Smart +## +## 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 . +######################################################################################################### + +APP_NAME = tzmtest +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 tzpu. + #APP_C_SRC = $(APP_COMMON_DIR)/pins_teensy.c $(APP_COMMON_DIR)/analog.c $(COMMON_DIR)/tranzputer.c + APP_C_SRC = $(COMMON_DIR)/tranzputer.c + CFLAGS = + CPPFLAGS = + LDFLAGS = + LIBS = +else + + # Modules making up tcpu. + 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 diff --git a/apps/tzmtest/tzmtest.c b/apps/tzmtest/tzmtest.c new file mode 100755 index 0000000..6522aa7 --- /dev/null +++ b/apps/tzmtest/tzmtest.c @@ -0,0 +1,338 @@ +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Name: tzmtest.c +// Created: July 2019 +// Author(s): Philip Smart +// Description: A TranZPUter helper utility, allowing the realtime display of the tranZPUter +// or host mainboard memory. Code originates from the original zputa mtest application. +// +// Credits: +// Copyright: (c) 2019-2020 Philip Smart +// +// History: May 2021 - Initial framework creation. +// +// 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 . +///////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(__K64F__) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "k64f_soc.h" + #include <../../libraries/include/stdmisc.h> +#elif defined(__ZPU__) + #include + #include + #include "zpu_soc.h" + #include + #include + #include +#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 + +// +#include "app.h" +#include +#include "tzmtest.h" + +// Utility functions. +#include "tools.c" + +// Version info. +#define VERSION "v1.0" +#define VERSION_DATE "15/05/2021" +#define APP_NAME "TZMTEST" + +// 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(" -a | --start Start address.\n"); + printf("\nOptions:-\n"); + printf(" -e | --end End address (alternatively use --size).\n"); + printf(" -s | --size Size of memory block to test (alternatively use --end).\n"); + printf(" -f | --fpga Operations will take place in the FPGA memory. Default without this flag is to target the tranZPUter memory.\n"); + printf(" -i | --iter Number of test iterations, default = 1.\n"); + printf(" -t | --test Specify test as a bit value, bit 0 = R/W inc ascending test, 1 = R/W inc walking test, 2 = W ascending then R,\n"); + printf(" bit 3 = W walking then R, bit 4 = echo and stick bit test.\n"); + //printf(" -w " --width Specify memory width tests reqd as a bit value, bit 0 = 8 bit, bit 1 = 16 bit, bit 2 = 32 bit.\n"); + printf(" -v | --verbose Output more messages.\n"); + + printf("\nExamples:\n"); + printf(" tzmtest -a 0x000000 -s 0x20000 # Test 128K tranZPUter memory from 0x000000 to 0x020000.\n"); + +} + + +// 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. + // + uint32_t startAddr = 0xFFFFFFFF; + uint32_t endAddr = 0xFFFFFFFF; + uint32_t memSize = 0xFFFFFFFF; + uint32_t iter = 1; // Default to 1 iteration. + uint16_t test = 0x00FF; // Default to all tests. + uint16_t width = 0x0007; // Default to all widths. + uint32_t testsToDo; + uint8_t retCode = 0; + int argc = 0; + int help_flag = 0; + int fpga_flag = 0; + int mainboard_flag = 0; + //int mempage_flag = 0; + int verbose_flag = 0; + int opt; + long val = 0; + char *argv[20]; + char *ptr = strtok((char *)param1, " "); + + // Initialisation. + + // 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}, + {"start", 'a', OPTPARSE_REQUIRED}, + {"end", 'e', OPTPARSE_REQUIRED}, + {"size", 's', OPTPARSE_REQUIRED}, + {"fpga", 'f', OPTPARSE_NONE}, + {"mainboard", 'm', OPTPARSE_NONE}, + {"iter", 'i', OPTPARSE_REQUIRED}, + {"test", 't', OPTPARSE_REQUIRED}, + //{"width", 'w', 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': + fpga_flag = 1; + break; + + case 'm': + mainboard_flag = 1; + break; + + case 'a': + if(xatoi(&options.optarg, &val) == 0) + { + printf("Illegal numeric (-a):%s\n", options.optarg); + return(5); + } + startAddr = (uint32_t)val; + break; + + case 'e': + if(xatoi(&options.optarg, &val) == 0) + { + printf("Illegal numeric (-e):%s\n", options.optarg); + return(6); + } + endAddr = (uint32_t)val; + break; + + case 's': + if(xatoi(&options.optarg, &val) == 0) + { + printf("Illegal numeric (-s):%s\n", options.optarg); + return(7); + } + memSize = (uint32_t)val; + break; + + case 'i': + if(xatoi(&options.optarg, &val) == 0) + { + printf("Illegal numeric (-i):%s\n", options.optarg); + return(8); + } + iter = (uint32_t)val; + break; + + case 't': + if(xatoi(&options.optarg, &val) == 0) + { + printf("Illegal numeric (-t):%s\n", options.optarg); + return(8); + } + test = (uint32_t)val; + break; + + //case 'w': + // if(xatoi(&options.optarg, &val) == 0) + // { + // printf("Illegal numeric (-w):%s\n", options.optarg); + // return(8); + // } + // width = (uint32_t)val; + // 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(startAddr == 0xFFFFFFFF) + { + printf("Please define the start address, size will default to 0x100.\n"); + return(10); + } + if(endAddr == 0xFFFFFFFF && memSize == 0xFFFFFFFF) + { + endAddr = startAddr + 0x100; + } else if(endAddr == 0xFFFFFFFF) + { + endAddr = startAddr + memSize; + } + if(endAddr < startAddr) + { + printf("Start Address must be greater than End Address.\n"); + return(11); + } + if(mainboard_flag == 1 && fpga_flag == 1) + { + printf("Please specify only one target, --mainboard, --fpga or default to tranZPUter memory.\n"); + return(12); + } + if(mainboard_flag == 1 && (startAddr > 0x10000 || endAddr > 0x10000)) + { + printf("Mainboard only has 64K, please change the address or size.\n"); + return(13); + } + if(fpga_flag == 1 && (startAddr >= TZ_MAX_FPGA_MEM || endAddr > TZ_MAX_FPGA_MEM)) + { + printf("FPGA only has a %dM window, please change the address or size.\n", TZ_MAX_FPGA_MEM/1024000); + return(14); + } + if(mainboard_flag == 0 && fpga_flag == 0 && (startAddr >= TZ_MAX_Z80_MEM || endAddr > TZ_MAX_Z80_MEM)) + { + printf("tranZPUter board only has %dK, please change the address or size.\n", TZ_MAX_Z80_MEM/1024); + return(15); + } + + // Setup the test/width indicator flag. + testsToDo = (width << 16) | test; + + // A very simple test, this needs to be updated with a thorough bit pattern and location test. + if(verbose_flag) + printf( "Check memory addr 0x%08lX to 0x%08lX over %ld iteration(s).\n", startAddr, endAddr, iter ); + + // Perform test for given number of iterations. + for(uint32_t idx=0; idx < iter && retCode == 0; idx++) + { + if(testsToDo & 0x00010000) + { + retCode = testZ80Memory(startAddr, endAddr, testsToDo, verbose_flag, mainboard_flag == 1 ? MAINBOARD : fpga_flag == 1 ? FPGA : TRANZPUTER); + } + //if(testsToDo & 0x00020000) + //{ + // test16bit(startAddr, endAddr, testsToDo); + //} + //if(testsToDo & 0x00040000) + //{ + // test32bit(startAddr, endAddr, testsToDo); + //} + } + + // Terminate output if in verbose mode. + if(verbose_flag) + printf("\n"); + + // Indicate any failure if we are in silent mode. + if(retCode != 0 && verbose_flag == 0) + printf("Memory test failed with return code:%d, use --verbose flag for more detail.\n", retCode); + + return(0); +} + +#ifdef __cplusplus +} +#endif diff --git a/apps/tzmtest/tzmtest.h b/apps/tzmtest/tzmtest.h new file mode 100755 index 0000000..a0c2357 --- /dev/null +++ b/apps/tzmtest/tzmtest.h @@ -0,0 +1,50 @@ +///////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Name: tzmtest.h +// Created: May 2021 +// Author(s): Philip Smart +// Description: A TranZPUter helper utility, allowing to test the onboard tranZPUter card memory +// or externally accessible FPGA BRAM. +// Credits: +// Copyright: (c) 2019-2020 Philip Smart +// +// History: July 2019 - Initial framework creation. +// April 2020 - Updates to function with the K64F processor and zOS. +// +// 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 . +///////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifndef TZMTEST_H +#define TZMTEST_H + +#ifdef __cplusplus + extern "C" { +#endif + +// Constants. + +// Application execution constants. +// + +// Components to be embedded in the program. +// +// Memory components to be embedded in the program. +#define BUILTIN_MEM_TEST 1 + +#ifdef __cplusplus +} +#endif +#endif // TZMTEST_H diff --git a/common/tranzputer.c b/common/tranzputer.c index ab935d5..fe804fd 100644 --- a/common/tranzputer.c +++ b/common/tranzputer.c @@ -61,6 +61,7 @@ // The bug occurs due to an interaction between the heap management // and threads. // v1.7 May 2021 - Changes to use 512K-1Mbyte Z80 Static RAM, build time configurable. +// Added memory test routines to validate tranZPUter memory. // // Notes: See Makefile to enable/disable conditional components // @@ -1619,6 +1620,298 @@ void fillZ80Memory(uint32_t addr, uint32_t size, uint8_t data, enum TARGETS targ return; } +// A memory test method extracted from the base zputa code for use with the tranZPUter card. +// +uint8_t testZ80Memory(uint32_t start, uint32_t end, uint32_t testsToDo, int verbose, enum TARGETS target) +{ + // Locals. + uint32_t memPtr; + uint32_t memPtr2; + unsigned long count; + unsigned long count2; + uint8_t data; + uint8_t readBack; + uint8_t retCode = 0; + uint32_t errCnt = 0; + + + // Sanity checks. + // + if((target == MAINBOARD && (start > 0x10000 || end > 0x10000)) || (target == TRANZPUTER && (start > TZ_MAX_Z80_MEM || end > TZ_MAX_Z80_MEM)) || (target == FPGA && (start > TZ_MAX_FPGA_MEM || end > TZ_MAX_FPGA_MEM)) ) + return(1); + + // If the Z80 is in RUN mode, request the bus. + // This mechanism allows for the Z80 BUS to remain under the tranZPUter control for multiple transactions. + // + if(z80Control.ctrlMode == Z80_RUN) + { + // Request the board according to the target flag, target = MAINBOARD then the mainboard is controlled otherwise the tranZPUter board. + if(target == TRANZPUTER || target == FPGA) + { + reqTranZPUterBus(DEFAULT_BUSREQ_TIMEOUT, target); + } else + { + reqMainboardBus(DEFAULT_BUSREQ_TIMEOUT); + } + + // If successful, setup the control pins for upload mode. + // + if(z80Control.ctrlMode != Z80_RUN) + { + // Setup the pins to perform a write operation. + // + setZ80Direction(WRITE); + + // Setup the control latch to the required starting configuration. + writeCtrlLatch(z80Control.curCtrlLatch); + } + } else + { + // See if the bus needs changing. + // + enum CTRL_MODE newMode = (target == MAINBOARD) ? MAINBOARD_ACCESS : TRANZPUTER_ACCESS; + reqZ80BusChange(newMode); + } + + // Ensure we dont close the bus connection during the tests. + z80Control.holdZ80 = 1; + + // If we have bus control, complete the task, + // + if( z80Control.ctrlMode != Z80_RUN ) + { + // Setup the pins to perform a write operation (after setting the latch to starting value). + // + writeCtrlLatch(z80Control.curCtrlLatch); + + // Ascending value test write with readback. + if(testsToDo & 0x00000001 && retCode == 0) + { + if(verbose) + printf( "\rR/W 8bit ascending test pattern... " ); + memPtr = start; + data = 0x00; + count = end - start; + while( count-- && errCnt <= 20) + { + setZ80Direction(WRITE); + writeZ80Memory(memPtr, data, target); + setZ80Direction(READ); + if( (readBack=readZ80Memory(memPtr)) != data ) + { + if(verbose) + printf( "\rError (8bit rwap) at 0x%08lX (%02x:%02x)\n", memPtr, readBack, data ); + if(errCnt++ == 20) + { + if(verbose) + printf( "\rError count (8bit rwap) > 20, stopping test.\n"); + retCode = 10; + } + } + memPtr++; + data++; + if( data >= 0xFF ) + data = 0x00; + } + } + + // Walking value test write with readback. + if(testsToDo & 0x00000002 && retCode == 0) + { + if(verbose) + printf( "\rR/W 8bit walking test pattern... " ); + memPtr = start; + data = 0x55; + count = end - start; + errCnt = 0; + while( count-- && errCnt <= 20) + { + setZ80Direction(WRITE); + writeZ80Memory(memPtr, data, target); + setZ80Direction(READ); + if( (readBack=readZ80Memory(memPtr)) != data ) + { + if(verbose) + printf( "\rError (8bit rwwp) at 0x%08lX (%02x:%02x)\n", memPtr, readBack, data ); + if(errCnt++ == 20) + { + if(verbose) + printf( "\rError count (8bit rwwp) > 20, stopping test.\n"); + retCode = 20; + } + } + memPtr++; + if( data == 0x55 ) + data = 0xAA; + else + data = 0x55; + } + } + + // Ascending value test write block then verify block. + if(testsToDo & 0x00000004 && retCode == 0) + { + if(verbose) + printf( "\rWrite 8bit ascending test pattern... " ); + memPtr = start; + data = 0x00; + count = end - start; + while( count-- ) + { + setZ80Direction(WRITE); + writeZ80Memory(memPtr, data, target); + setZ80Direction(READ); + if( (readBack=readZ80Memory(memPtr)) != data ) + { + if(verbose) + printf( "\rError (8bit wap) at 0x%08lX (%02x:%02x)\n", memPtr, readBack, data ); + if(errCnt++ == 20) + { + if(verbose) + printf( "\rError count (8bit rwwp) > 20, stopping test.\n"); + retCode = 30; + } + } + memPtr++; + data++; + if( data >= 0xFF ) + data = 0x00; + } + + if(verbose) + printf( "\rRead 8bit ascending test pattern... " ); + memPtr = start; + data = 0x00; + count = end - start; + errCnt = 0; + while( count-- && errCnt <= 20) + { + setZ80Direction(WRITE); + writeZ80Memory(memPtr, data, target); + setZ80Direction(READ); + if( (readBack=readZ80Memory(memPtr)) != data ) + { + if(verbose) + printf( "\rError (8bit ap) at 0x%08lX (%02x:%02x)\n", memPtr, readBack, data ); + if(errCnt++ == 20) + { + if(verbose) + printf( "\rError count (8bit ap) > 20, stopping test.\n"); + retCode = 40; + } + } + memPtr++; + data++; + if( data >= 0xFF ) + data = 0x00; + } + } + + // Walking value test write block then verify block. + if(testsToDo & 0x00000008 && retCode == 0) + { + if(verbose) + printf( "\rWrite 8bit walking test pattern... " ); + memPtr = start; + data = 0x55; + count = end - start; + setZ80Direction(WRITE); + while( count-- ) + { + writeZ80Memory(memPtr, data, target); + if( data == 0x55 ) + data = 0xAA; + else + data = 0x55; + memPtr++; + } + + if(verbose) + printf( "\rRead 8bit walking test pattern... " ); + memPtr = start; + data = 0x55; + count = end - start; + errCnt = 0; + setZ80Direction(READ); + while( count-- && errCnt <= 20) + { + if( (readBack=readZ80Memory(memPtr)) != data ) + { + if(verbose) + printf( "\rError (8bit wp) at 0x%08lX (%02x:%02x)\n", memPtr, readBack, data ); + if(errCnt++ == 20) + { + if(verbose) + printf( "\rError count (8bit wp) > 20, stopping test.\n"); + retCode = 50; + } + } + memPtr++; + if( data == 0x55 ) + data = 0xAA; + else + data = 0x55; + } + } + + // Echo and sticky bit test, more complex as the array has to be scanned for each set to see if any bit in the memory array + // has been set with a write to 1 location or bits are staying stuck. + if(testsToDo & 0x00000010 && retCode == 0) + { + if(verbose) + printf( "\r8bit echo and sticky bit test... " ); + memPtr = start; + count = end - start; + errCnt = 0; + fillZ80Memory(start, end - start, 0x00, target); + while( count-- && errCnt <= 20) + { + setZ80Direction(WRITE); + writeZ80Memory(memPtr, 0xFF, target); + + memPtr2 = start; + count2 = end - start; + while( count2-- && errCnt <= 20) + { + setZ80Direction(READ); + readBack=readZ80Memory(memPtr2); + if( readBack != 0x00 && readBack != readZ80Memory(memPtr)) + { + if(verbose) + printf( "\rError (8bit es) at 0x%08lx:0x%08lX (%02x:%02x)\n", memPtr, memPtr2, readBack, 0x00 ); + setZ80Direction(WRITE); + writeZ80Memory(memPtr2, 0x00, target); + if(errCnt++ == 20) + { + if(verbose) + printf( "\rError count (8bit es) > 20, stopping test.\n"); + retCode = 60; + } + } + memPtr2++; + } + setZ80Direction(WRITE); + writeZ80Memory(memPtr, 0x00, target); + memPtr++; + } + } + } + + // Release the bus if it is not being held for further transations. + // + z80Control.holdZ80 = 1; + if(z80Control.holdZ80 == 0 && z80Control.ctrlMode != Z80_RUN) + { + // Restore the control latch to its original configuration. + // + writeCtrlLatch(z80Control.runCtrlLatch); + releaseZ80(); + } + + // Return completion code. + return(retCode); +} + // A method to read the full video frame buffer from the Sharp MZ80A and store it in local memory (control structure). // No refresh cycles are needed as we grab the frame but between frames a full refresh is performed. // @@ -4217,7 +4510,7 @@ uint32_t getServiceAddr(void) // zOS addr = TZSVC_CMD_STRUCT_ADDR_ZOS; } -printf("getServiceAddr:%02x,%02x,%02x,%01x,%08lx,%02x\n", z80Control.runCtrlLatch, z80Control.curCtrlLatch, memoryMode, cpuConfig, addr, svcControl.cmd); +//printf("getServiceAddr:%02x,%02x,%02x,%01x,%08lx,%02x\n", z80Control.runCtrlLatch, z80Control.curCtrlLatch, memoryMode, cpuConfig, addr, svcControl.cmd); return(addr); } diff --git a/include/tools.h b/include/tools.h index 46308bd..e67099a 100644 --- a/include/tools.h +++ b/include/tools.h @@ -10,6 +10,7 @@ // Copyright: (c) 2019-21 Philip Smart // // History: January 2019 - Initial script written. +// May 2021 - Added memory test tz command. // ///////////////////////////////////////////////////////////////////////////////////////////////////////// // This source file is free software: you can redistribute it and#or modify @@ -113,6 +114,7 @@ extern "C" { #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_TZ_MTEST 158 // tranZPUter memory test tool. #define CMD_BADKEY -1 #define CMD_NOKEY 0 #define CMD_GROUP_DISK 1 @@ -391,24 +393,25 @@ static t_cmdstruct cmdTable[] = { #if (defined(BUILTIN_MISC_TEST) && BUILTIN_MISC_TEST == 1) || (defined(BUILTIN_MISC_HELP) == 1 && BUILTIN_MISC_HELP == 1) { "test", BUILTIN_MISC_TEST, CMD_MISC_TEST, CMD_GROUP_MISC }, #endif + #if defined __SHARPMZ__ #if (defined(BUILTIN_MISC_CLS) && BUILTIN_MISC_CLS == 1) || (defined(BUILTIN_MISC_HELP) == 1 && BUILTIN_MISC_HELP == 1) { "cls", BUILTIN_DEFAULT, CMD_MISC_CLS, CMD_GROUP_MISC }, #endif #if (defined(BUILTIN_MISC_Z80) && BUILTIN_MISC_Z80 == 1) || (defined(BUILTIN_MISC_HELP) == 1 && BUILTIN_MISC_HELP == 1) { "z80", BUILTIN_DEFAULT, CMD_MISC_Z80, CMD_GROUP_MISC }, #endif + #endif // Applications - most are not built in so dont need to be in this table or just placed here commented out for reference. { "tbasic", BUILTIN_DEFAULT, CMD_APP_TBASIC, CMD_GROUP_APP }, { "mbasic", BUILTIN_DEFAULT, CMD_APP_MBASIC, CMD_GROUP_APP }, { "kilo", BUILTIN_DEFAULT, CMD_APP_KILO, CMD_GROUP_APP }, { "ed", BUILTIN_DEFAULT, CMD_APP_ED, CMD_GROUP_APP }, - #if defined __SHARPMZ__ - #endif #if defined __TRANZPUTER__ { "tzpu", BUILTIN_DEFAULT, CMD_TZ_TZPU, CMD_GROUP_TZ }, { "tzload", BUILTIN_DEFAULT, CMD_TZ_LOAD, CMD_GROUP_TZ }, { "tzdump", BUILTIN_DEFAULT, CMD_TZ_DUMP, CMD_GROUP_TZ }, { "tzclear", BUILTIN_DEFAULT, CMD_TZ_CLEAR, CMD_GROUP_TZ }, + { "tzmtest", BUILTIN_DEFAULT, CMD_TZ_MTEST, CMD_GROUP_TZ }, { "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 }, @@ -528,6 +531,7 @@ static t_helpstruct helpTable[] = { { CMD_TZ_LOAD, "--help", "Memory load/save tool" }, { CMD_TZ_DUMP, "--help", "Memory dump tool" }, { CMD_TZ_CLEAR, "--help", "Memory clearing tool" }, + { CMD_TZ_MTEST, "--help", "Memory testing tool" }, { CMD_TZ_CLK, "--help", "CPU Freq set tool" }, { CMD_TZ_RESET, "--help", "Remote reset tool" }, { CMD_TZ_IO, "--help", "I/O read/write tool" }, diff --git a/include/tranzputer.h b/include/tranzputer.h index 8248dc5..7a2a8e6 100755 --- a/include/tranzputer.h +++ b/include/tranzputer.h @@ -836,6 +836,7 @@ 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); +uint8_t testZ80Memory(uint32_t, uint32_t, uint32_t, int, enum TARGETS); void captureVideoFrame(enum VIDEO_FRAMES, uint8_t); void refreshVideoFrame(enum VIDEO_FRAMES, uint8_t, uint8_t); FRESULT loadVideoFrameBuffer(char *, enum VIDEO_FRAMES); diff --git a/libraries/lib/libimath2-k64f.a b/libraries/lib/libimath2-k64f.a index d89d144dc18153f2cb3a111d4cde572e802f62ee..4133f7bd523e896cd24a51d6824b16aabf657b36 100644 GIT binary patch delta 87 zcmZ2dx}?5eFBAL=9NT*mzmzE+bBD4V)pT6OV zWRTRQ(4l%DXG_E>(4i8XLg)(x71Tk{{%m^la?iEf`MclGIk)Qis;CVtVWz(VVLM*Nfo5%mwEdOBFfx*l^-if|&$R81t_`1X*Tm>70i#m|ak@Wexiu zc`ohl)I1JvvopgEW}~?KS+!ju?fUDPd}(04u-__QmclxID+N^Rpj>27SJR#JJdE3K zWS__}KRuFi4ZB`Q;MCu@OdwG3__n|VB$k_(RvWWv+6uue7wD=J z4)1}Z^rIJE$c-D`3F!F%ybnn6!WWg|@V%|MDub*^_{B`l$`^>x`ZV}7*=|Ys1&Yb;isZ#d*BYl>G>2}s6Dj`n1W7EF^ l@U;yxOORqb+9^Yx6Gt#5XsrS{Rwr&n6E*mwvn{|8dd+&YU_uk9j+46Tbv96+{qpQ1zKWX?VF~V-i zADP09(owsaqsry2IO}%X%L^lN!Vcq-z{*hY_g9)&@Bw_7Y@TuumnizMsk5HuC6)7H zw6Dk~4CemTJlH<`LOJ>)>Hk_7o(xqIugbYGHM8g>kN%ZsbB;%6e94MMF+g!)ufQ(t z#Y@h(7Z3J}b(Qnr`_U8iqpF;mdc2f%d+|8quxi=!G{yQ(a&#K{rP*N@zUC&Zf_}*K zO;J!c-S&88n&u@{3E|-PoF$?k=lWNnc_!K+RV*q|w&Q{k0@zzEoKdUh!NV>aA!r_+ zmxTxLvetH3Af(We>4l3b<7PY)2jHFv~JQFeyAwITu c4k=1xO)11SbC4uNe;Nzlz?Wr4JIb!(56}VTlK=n! diff --git a/libraries/lib/libumansi-zpu.a b/libraries/lib/libumansi-zpu.a index 169007df2f1a7a1988d4973fbf200e5373f8a88c..3fc524271d721c3bc2f745cf55f62b65c1d1c75a 100644 GIT binary patch delta 754 zcmYLH-77<37_YNgMq?M+IW#P(NirYjD3&%w%4$u?8a2s&^cmrA4^leeJx@xqF`X`F%Xk@0?=BR?OJ;y^ij#-hM^Nw_FM3vKNRT z*vwjY4~y_tF^_%NE9y&HC!9Mqd?RWCG}j&H>#@sv7lI;i8Wl#B^U)#s|vQAV9ItD&W zet8}mESUOqPW2atxV{YT;dPv`405BZ*b{XcHX^sEMFbH-(I4JJc%0|QbVZn%@LOE! z^BPAVI`_cMRGX9U{h#+-4)I2z9`f@pGfQ?y0veb3-7*l>fmn89Y2}^op_2y*>}w6k zWtj#yKP|lA$wjv-xiuRvX@KLDF$r5cB}o7n7^d z&oKhe**z1hKENyC1R%Pp7Xx%xqCi-AJ6Zp<_y)G;n>kQG&DLkER=h1Ij!^p;y44T zC3DCM?+q)g4?3(;N*si1lgMT$odB`5MEO#*Xor|tG*XR>Y=e4-o8hsB#~F|!-flRz z-OxD%9W`1@3I;sRKh`5|3G#i{%maJoUAiaYERb}cv`|mXZ}(C@FQK#z2F5=LpI7w* z6BVMb>=pghNvh9-Ike4o_y>jQP1d9I0_=nzm=@x!5QzNJ9)dCYKdfto#aWlmReav! z%tzT<;C{Z}q}|PH|6VRIyj-zEd8L*766Z)j*E-G314=g%tWV8Y-}oSRDE*TSj9Zr*rPcfWKzXDLMXn>1@}of3hqGx8kl9n^I><;X+-aFGZ3XpmE(QA2z J)pDiH_z$F2<4^zq diff --git a/libraries/lib/libummath-k64f.a b/libraries/lib/libummath-k64f.a index 400e289b7b38643c66038d9fa5ba593bfb6b2f5f..ed06d9c939780cfae1a8e15dc6ad36d57cfd8afd 100644 GIT binary patch delta 27 dcmaDN@rt`u0@77Cfe#Cza#^1b7u8R{Y zx7ki(5{x~0ot(txcZOOp{$@GrTX6P2mtVXvJ^zA=VC>0!w8?5%@;_uurJKwEe2X(*MWIGMX&Aa!N zaHsJ=_Q+`F1_P`Xf@l+cUuoGCui-nx#h_WI3E;LmhWD30|3jZ BYD@qC delta 336 zcmZ4Tg?Y&r<_R)v1_mak7Umn32h47FhV&2rYa;Ou`czj$GK{sk4m*pvBgOKk2-;DW20mw5@;B+On&pbna^Nsu-cD{zjMRve7AlbA55Q}hUDhm v`%2+zLGJcDp#YTj delta 359 zcmeyfiRsTKrU^1^1_makMur=e0?2Xo4lbhb@N|Eb!H^7%?_$_Q20MIBDlcvMh0N}a*R1p_!Df8K+K2A7dU9}Le+1c z=W7J94=VR2FozE&7ndN%ifrzT)Eg+~^kisoAj@AU_yX}4)T{@!TOjU)@;5a0An|u^ i{@Z#P&Y$O7zS*~HHIYh#5R50tri4$mfT0N^+Z-2eap delta 39 kcmX?SaL!IYh#5R50tri4$mfT0N;TM)Bpeg diff --git a/libraries/lib/libummisc-zpu.a b/libraries/lib/libummisc-zpu.a index 406635a05b4d5762031b5435cbaa79a38484ac75..a6126cf94fe8a680a2d823b47bb99b61410dd15c 100644 GIT binary patch delta 45 ncmZ1{wN7e+44a{Wv8AcSM5O>IYx4s(N9N5tnH8B40)A`&A1n-A delta 45 ncmZ1{wN7e+44Z+0iK&svM5O>IYx4s(N9N5tnH8B40)A`&99s-L diff --git a/libraries/lib/libumstdio-k64f.a b/libraries/lib/libumstdio-k64f.a index c46bcb77e4ff785cbe0683e90c6fb5616d4925dd..6d46298c18cac575e52467beca8324a3a11de03d 100644 GIT binary patch delta 371 zcmdn=k!90ImI*R!h6cu#mS!83N*JNc$sd9xHg93{;zjVqH%s#$=0Wf!Hvf@ULy{NU zY^V7`8X+&f+1YhDAC$lOLoljZqeKgswVMlS=W!$J)9y@1vL|Y?oebONA5)JZiHUE% zy=XfMfBpL7NNy3|JbCYFxO_pa#O9h)lThurrVf|?5G=kq|4}iD{{QcVQRMai1S9je k&*xx7C@82E-+o?%QJD+L7u)&e8OxEhNNiuC&B(_K04?NruK)l5 delta 371 zcmdn=k!90ImI*R!1_mak78VuB{u(&Rzs2( z+ia)#LK-12zS-GzIUkh2`9mXOYOt37+acJY*f-SVuA6lWI-&9wV7-@$qoDE-zDL;#sNE1gPc;h*0J*ebO8@`> delta 355 zcmbR6k8uJJ$*>t1n3x)wY*f-Ju+R{RJ^AFLe%#zgZyj x9F%PWcH{4y=TN;SlLazeH|rL3BFT$wzEm6qmj{KBN7)Lf-5~v9n|Z2PSO5T`U`PM} diff --git a/rtl/IOCP_zOS_BootROM.vhd b/rtl/IOCP_zOS_BootROM.vhd index 3ed75cd..faadb88 100644 --- a/rtl/IOCP_zOS_BootROM.vhd +++ b/rtl/IOCP_zOS_BootROM.vhd @@ -16010,11 +16010,11 @@ shared variable ram : ram_type := 16972 => x"7a4f5300", 16973 => x"2a2a2025", 16974 => x"73202800", - 16975 => x"31312f30", + 16975 => x"31352f30", 16976 => x"352f3230", 16977 => x"32310000", 16978 => x"76312e33", - 16979 => x"62000000", + 16979 => x"00000000", 16980 => x"205a5055", 16981 => x"2c207265", 16982 => x"76202530", diff --git a/rtl/TZSW_DualPort3264BootBRAM.vhd b/rtl/TZSW_DualPort3264BootBRAM.vhd index a16adba..817ee28 100644 --- a/rtl/TZSW_DualPort3264BootBRAM.vhd +++ b/rtl/TZSW_DualPort3264BootBRAM.vhd @@ -62249,7 +62249,7 @@ architecture arch of DualPort3264BootBRAM is 7460 => x"20", 7461 => x"00", 7462 => x"2a", - 7463 => x"31", + 7463 => x"35", 7464 => x"31", 7465 => x"00", 7466 => x"20", @@ -71369,7 +71369,7 @@ architecture arch of DualPort3264BootBRAM is 7462 => x"2a", 7463 => x"31", 7464 => x"32", - 7465 => x"62", + 7465 => x"00", 7466 => x"2c", 7467 => x"32", 7468 => x"73", diff --git a/rtl/TZSW_DualPortBootBRAM.vhd b/rtl/TZSW_DualPortBootBRAM.vhd index a34696b..1c6b0c0 100644 --- a/rtl/TZSW_DualPortBootBRAM.vhd +++ b/rtl/TZSW_DualPortBootBRAM.vhd @@ -51457,7 +51457,7 @@ architecture arch of DualPortBootBRAM is 14924 => x"4f", 14925 => x"2a", 14926 => x"20", - 14927 => x"31", + 14927 => x"35", 14928 => x"2f", 14929 => x"31", 14930 => x"31", @@ -69692,7 +69692,7 @@ architecture arch of DualPortBootBRAM is 14928 => x"35", 14929 => x"32", 14930 => x"76", - 14931 => x"62", + 14931 => x"00", 14932 => x"20", 14933 => x"2c", 14934 => x"76", diff --git a/rtl/TZSW_SinglePortBootBRAM.vhd b/rtl/TZSW_SinglePortBootBRAM.vhd index 58d9c81..f032227 100644 --- a/rtl/TZSW_SinglePortBootBRAM.vhd +++ b/rtl/TZSW_SinglePortBootBRAM.vhd @@ -51452,7 +51452,7 @@ architecture arch of SinglePortBootBRAM is 14924 => x"4f", 14925 => x"2a", 14926 => x"20", - 14927 => x"31", + 14927 => x"35", 14928 => x"2f", 14929 => x"31", 14930 => x"31", @@ -69687,7 +69687,7 @@ architecture arch of SinglePortBootBRAM is 14928 => x"35", 14929 => x"32", 14930 => x"76", - 14931 => x"62", + 14931 => x"00", 14932 => x"20", 14933 => x"2c", 14934 => x"76", diff --git a/rtl/zOS_BootROM.vhd b/rtl/zOS_BootROM.vhd index afd977b..fe40d31 100644 --- a/rtl/zOS_BootROM.vhd +++ b/rtl/zOS_BootROM.vhd @@ -14989,11 +14989,11 @@ shared variable ram : ram_type := 14924 => x"7a4f5300", 14925 => x"2a2a2025", 14926 => x"73202800", - 14927 => x"31312f30", + 14927 => x"31352f30", 14928 => x"352f3230", 14929 => x"32310000", 14930 => x"76312e33", - 14931 => x"62000000", + 14931 => x"00000000", 14932 => x"205a5055", 14933 => x"2c207265", 14934 => x"76202530", diff --git a/rtl/zOS_DualPort3264BootBRAM.vhd b/rtl/zOS_DualPort3264BootBRAM.vhd index 000add3..1bb8203 100644 --- a/rtl/zOS_DualPort3264BootBRAM.vhd +++ b/rtl/zOS_DualPort3264BootBRAM.vhd @@ -62249,7 +62249,7 @@ architecture arch of DualPort3264BootBRAM is 7460 => x"20", 7461 => x"00", 7462 => x"2a", - 7463 => x"31", + 7463 => x"35", 7464 => x"31", 7465 => x"00", 7466 => x"20", @@ -71369,7 +71369,7 @@ architecture arch of DualPort3264BootBRAM is 7462 => x"2a", 7463 => x"31", 7464 => x"32", - 7465 => x"62", + 7465 => x"00", 7466 => x"2c", 7467 => x"32", 7468 => x"73", diff --git a/rtl/zOS_DualPortBootBRAM.vhd b/rtl/zOS_DualPortBootBRAM.vhd index 62d2209..3870bc1 100644 --- a/rtl/zOS_DualPortBootBRAM.vhd +++ b/rtl/zOS_DualPortBootBRAM.vhd @@ -51457,7 +51457,7 @@ architecture arch of DualPortBootBRAM is 14924 => x"4f", 14925 => x"2a", 14926 => x"20", - 14927 => x"31", + 14927 => x"35", 14928 => x"2f", 14929 => x"31", 14930 => x"31", @@ -69692,7 +69692,7 @@ architecture arch of DualPortBootBRAM is 14928 => x"35", 14929 => x"32", 14930 => x"76", - 14931 => x"62", + 14931 => x"00", 14932 => x"20", 14933 => x"2c", 14934 => x"76", diff --git a/rtl/zOS_SinglePortBootBRAM.vhd b/rtl/zOS_SinglePortBootBRAM.vhd index 3d77ab0..82dd1c0 100644 --- a/rtl/zOS_SinglePortBootBRAM.vhd +++ b/rtl/zOS_SinglePortBootBRAM.vhd @@ -51452,7 +51452,7 @@ architecture arch of SinglePortBootBRAM is 14924 => x"4f", 14925 => x"2a", 14926 => x"20", - 14927 => x"31", + 14927 => x"35", 14928 => x"2f", 14929 => x"31", 14930 => x"31", @@ -69687,7 +69687,7 @@ architecture arch of SinglePortBootBRAM is 14928 => x"35", 14929 => x"32", 14930 => x"76", - 14931 => x"62", + 14931 => x"00", 14932 => x"20", 14933 => x"2c", 14934 => x"76", diff --git a/startup/app_k64f_crt0.s b/startup/app_k64f_crt0.s index b361f6a..23a89cc 100644 --- a/startup/app_k64f_crt0.s +++ b/startup/app_k64f_crt0.s @@ -346,6 +346,8 @@ BSS_END: .word __bss_section_end__ .equ funcAddr, funcAddr+funcNext; defapifunc fillZ80Memory funcAddr .equ funcAddr, funcAddr+funcNext; + defapifunc testZ80Memory funcAddr + .equ funcAddr, funcAddr+funcNext; defapifunc captureVideoFrame funcAddr .equ funcAddr, funcAddr+funcNext; defapifunc refreshVideoFrame funcAddr diff --git a/startup/app_k64f_hwctl_crt0.s b/startup/app_k64f_hwctl_crt0.s index c1f326f..34373ad 100644 --- a/startup/app_k64f_hwctl_crt0.s +++ b/startup/app_k64f_hwctl_crt0.s @@ -346,6 +346,8 @@ BSS_END: .word __bss_section_end__ .equ funcAddr, funcAddr+funcNext; defapifunc fillZ80Memory funcAddr .equ funcAddr, funcAddr+funcNext; + defapifunc testZ80Memory funcAddr + .equ funcAddr, funcAddr+funcNext; defapifunc captureVideoFrame funcAddr .equ funcAddr, funcAddr+funcNext; defapifunc refreshVideoFrame funcAddr diff --git a/startup/mk20dx128.c b/startup/mk20dx128.c index a92fd9d..1f2edb6 100644 --- a/startup/mk20dx128.c +++ b/startup/mk20dx128.c @@ -1009,6 +1009,7 @@ void _ZPUTA_Vectors(void) __asm__ volatile ("b copyFromZ80"); __asm__ volatile ("b copyToZ80"); __asm__ volatile ("b fillZ80Memory"); + __asm__ volatile ("b testZ80Memory"); __asm__ volatile ("b captureVideoFrame"); __asm__ volatile ("b refreshVideoFrame"); __asm__ volatile ("b loadVideoFrameBuffer"); diff --git a/zOS/src/zOS.cpp b/zOS/src/zOS.cpp index 4356540..7d97713 100644 --- a/zOS/src/zOS.cpp +++ b/zOS/src/zOS.cpp @@ -121,8 +121,8 @@ #endif // Version info. -#define VERSION "v1.3b" -#define VERSION_DATE "11/05/2021" +#define VERSION "v1.3" +#define VERSION_DATE "15/05/2021" #define PROGRAM_NAME "zOS" // Utility functions.