/* * Copyright (C) 2004-2007 by egnite Software GmbH * Copyright (C) 2008 by egnite GmbH * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted 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 holders nor the names of * 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 OWNER 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. * * For additional information see http://www.ethernut.de/ * and Xilinx Application Note XAPP058. */ /* * $Log$ * Revision 1.1 2008/10/20 13:10:05 haraldkipp * Checked in. * */ #include #include #include #if defined(ETHERNUT2) || defined(ETHERNUT3) #include #include #include #include #include #elif defined(_MSC_VER) #include #endif #include "xsvf.h" #include "tapsm.h" #include "host.h" /*! * \file host.c * \brief Platform dependant routines.. */ /*! * \addtogroup xgHost */ /*@{*/ #ifdef XSVF_DEBUG /*! * \brief XSVF command names. * * Used for debugging output. */ static char *cmd_names[] = { "XCOMPLETE", "XTDOMASK", "XSIR", "XSDR", "XRUNTEST", "UNKNOWN", "UNKNOWN", "XREPEAT", "XSDRSIZE", "XSDRTDO", "XSETSDRMASKS", "XSDRINC", "XSDRB", "XSDRC", "XSDRE", "XSDRTDOB", "XSDRTDOC", "XSDRTDOE", "XSTATE", "XENDIR", "XENDDR", "XSIR2", "XCOMMENT", "XWAIT", "UNKNOWN" }; /*! * \brief TAP state names. * * Used for debugging output. */ static char *tap_names[] = { "Test-Logic-Reset", "Run-Test-Idle", "Select-DR-Scan", "Capture-DR", "Shift-DR", "Exit1-DR", "Pause-DR", "Exit2-DR", "Update-DR", "Select-IR-Scan", "Capute-IR", "Shift-IR", "Exit1-IR", "Pause-IR", "Exit2-IR", "Update-IR", "Unknown" }; #endif /*! * \brief Handle of XSVF file. */ static int fh; /*! * \brief Last error occured in this module. */ static int xsvf_err; /*! * \brief Initialize the platform dependant interface. * * All required hardware initializations should be done in this * routine. We may also initiate debug output. If the XSVF date * is located in a file system, then the file will be opened * here as well. * * \return Zero on success, otherwise an error code is returned. */ int XsvfInit(void) { #if defined(ETHERNUT2) || defined(ETHERNUT3) uint32_t baud = 115200; /* * Prepare standard output and display a banner. */ NutRegisterDevice(&devDebug0, 0, 0); freopen("uart0", "w", stdout); _ioctl(_fileno(stdout), UART_SETSPEED, &baud); printf("\n100 XSVF-Executor " XSVFEXEC_VERSION " on Nut/OS %s", NutVersionString()); NutSleep(100); /* * Register our device for the file system. */ NutRegisterDevice(&devUrom, 0, 0); #ifdef ETHERNUT2 /* * Disable JTAG. Ethernut 2 is using * * PF4 for target TCK. * PF5 for target TMS. * PF6 for target TDI. * PF7 for target TDO. */ NutEnterCritical(); outb(MCUCSR, _BV(JTD)); outb(MCUCSR, _BV(JTD)); NutExitCritical(); outb(DDRF, 0x70); #endif #ifdef ETHERNUT3 /* * Ethernut 3 is using * * P18 for target TCK. * P16 for target TMS. * P23 for target TDI. * P19 for target TDO. */ outr(PIO_OER, _BV(16) | _BV(18) | _BV(23)); outr(PIO_ODR, _BV(19)); #endif #elif defined(_WIN32) printf("\n100 XSVF-Executor " XSVFEXEC_VERSION " on WIN32"); #endif /* The XSVF file is expected in the UROM file system. */ fh = _open(XSVFNAME, _O_BINARY | _O_RDONLY); return (fh == -1) ? XE_DATAUNDERFLOW : 0; } /*! * \brief Shutdown the platform dependant interface. * * On most embedded platforms this routine will never return. * * \param rc Programming result code. */ void XsvfExit(int rc) { /* Close XSVF file. */ if(fh != -1) { _close(fh); } #ifdef ETHERNUT3 /* Re-enable UART0. */ outb(0x21000000, 0x20); NutSleep(100); #endif /* Display programming result. */ if(rc) { printf("\n4%02d ERROR\n", rc); } else { puts("\n199 OK"); } #if defined(ETHERNUT2) || defined(ETHERNUT3) /* Nut/OS applications never return. */ for (;;) { NutSleep(1000); } #endif } /*! * \brief Retrieve the last error occured in this module. * * \return Error code or 0 if no error occured. */ int XsvfGetError(void) { return xsvf_err; } /*! * \brief Get next byte from XSVF buffer. * * Call XsvfGetError() to check for errors, * * \return Byte value. */ uint8_t XsvfGetByte(void) { uint8_t rc; if(_read(fh, &rc, sizeof(rc)) != sizeof(rc)) { xsvf_err = XE_DATAUNDERFLOW; } #ifdef XSVF_DEBUG printf("[%u]", rc); #endif return rc; } /*! * \brief Get next command byte from XSVF buffer. * * \return XSVF command or XUNKNOWN if an error occured. */ uint8_t XsvfGetCmd(void) { uint8_t rc; #ifdef ETHERNUT2 static char cnt; if (++cnt == 0) { NutSleep(1); } #endif if(_read(fh, &rc, sizeof(rc)) != sizeof(rc) || rc >= XUNKNOWN) { rc = XUNKNOWN; } #ifdef XSVF_DEBUG printf("\n2%02d %s", rc, cmd_names[rc]); #endif return rc; } /*! * \brief Get next byte from XSVF buffer and select a TAP state. * * \param state0 Returned state, if the byte value is zero. * \param state1 Returned state, if the byte value is one. * * \return TAP state or UNKNOWN_STATE if an error occured. */ uint8_t XsvfGetState(uint8_t state0, uint8_t state1) { uint8_t rc; if(_read(fh, &rc, sizeof(rc)) != sizeof(rc) || rc > 1) { rc = UNKNOWN_STATE; } else if(rc) { rc = state1; } else { rc = state0; } #ifdef XSVF_DEBUG printf("{%s}", tap_names[rc]); #endif return rc; } /*! * \brief Get next short value from XSVF buffer. * * Call XsvfGetError() to check for errors, * * \return Short value. */ short XsvfGetShort(void) { short rc; if(_read(fh, &rc, sizeof(rc)) != sizeof(rc)) { xsvf_err = XE_DATAUNDERFLOW; return -1; } rc = ntohs(rc); #ifdef XSVF_DEBUG printf("[%d]", rc); #endif return rc; } /*! * \brief Get next long value from XSVF buffer. * * Call XsvfGetError() to check for errors, * * \return Long value. */ long XsvfGetLong(void) { long rc; if(_read(fh, &rc, sizeof(rc)) != sizeof(rc)) { xsvf_err = XE_DATAUNDERFLOW; rc = 0; } else { rc = ntohl(rc); } #ifdef XSVF_DEBUG printf("[%ld]", rc); #endif return rc; } /*! * \brief Read a specified number of bits from XSVF buffer. * * \param buf Pointer to the buffer which receives the bit string. * \param num Number of bits to read. * * \return Error code or 0 if no error occured. */ int XsvfReadBitString(void *buf, int num) { int len = (num + 7) / 8; if (len > MAX_BITVEC_BYTES) { xsvf_err = len = XE_DATAOVERFLOW; } else if(_read(fh, buf, len) < len) { xsvf_err = len = XE_DATAUNDERFLOW; } #ifdef XSVF_DEBUG else { uint8_t *cp = buf; printf("[%u:", num); while(len-- > 0) { printf("%02X", *cp); cp++; } printf("]"); } #endif return len; } /*! * \brief Skip comment in the XSVF buffer. * * \return Error code or 0 if no error occured. */ int XsvfSkipComment(void) { uint8_t ch; for(;;) { if(_read(fh, &ch, sizeof(ch)) != sizeof(ch)) { return (xsvf_err = XE_DATAUNDERFLOW); } if(ch == 0) { break; } #ifdef XSVF_DEBUG putchar(ch); #endif } return 0; } /*! * \brief Microsecond delay. * * \param usecs Number of microseconds. */ void XsvfDelay(long usecs) { #if defined(ETHERNUT2) || defined(ETHERNUT3) usecs = usecs / 1000L; NutSleep(usecs + 1); #elif defined(_MSC_VER) Sleep((usecs + 500L) / 1000L); #endif } /*@}*/